Last week, during the SharifCTF competition, I attempted to solve the pwn150 and pwn300 challenges, but was unable to solve them before they went offline.
Upon review, these challenges were intended to be solved as blind format string “dump-and-exploit” challenges, which was highly surprising given their relative point value. This technique is not overly complex, but I think is worth writing up – the best example I’ve found is for babyecho from a previous DefCON CTF.
To demonstrate this technique, I’m using a sample vulnerable binary (source here), and a simple netcat listener harness.
The core of the attack relies on a simple read-anywhere primitive, and the principle that a zero does not necessarily terminate printf – the format string argument to printf is actually copied wholly onto the stack, zeroes and all, in word-size units. This makes it possible to “seed” the stack with data containing zeroes, to a limited extent:
In this payload:
- The green portion prints a string at argument six, which is the red (0x601000)
- The blue is padding, to ensure the red offset ends up cleanly at an argument offset
- The red is a raw offset, including a null byte, which is copied onto the stack.
- The sample executable is 64-bit, but uses memset to clear a stack buffer before storing user input in there, meaning the remaining bytes of the red argument are zero. This may not be the case, if you’re targetting an address which has leftover re-used data in it – you may be able to solve this by sending it strings of decreasing length, using the terminating null byte to “clean” the buffer.
Sending the above example to a netcat harness running the sample executable should give you:
From here, you can quickly hack together a loop to dump anything, from the ELF header, to code:
At this point, the vulnerability becomes a non-blind format string.
You can find the wrapper script to begin dumping code here.