This is the fifth and final uncontrolled format string vulnerability exercise from the Protostar image at Exploit Exercises. In this one we are seizing control of the program execution to redirect to a specified function; however, in an attack scenario this could easily be the memory location of a piece of shellcode instead.
For this challenge we are given the following source:
Our input is again taken over stdin, so will have to pipe our exploit into the program. There is also a small hint in the source code if we read carefully: the program calls
_exit(1). We will be looking there for how to hijack the execution flow.
exit() is a libc function, so when the program is run its address is stored in the Global Offset Table(GOT) for later use. We can use an injected format string to overwrite this value with the address of the
hello() function. When the program calls
exit() it will look in the GOT for its address and execution will be redirected to our
hello() function instead.
To set this up we first need to find the location of our input on the stack:
Our input is at position 4. We can use two objdump calls to find the addresses of
We can again use Direct-Parameter Access (DPA) and shortwrites to build our exploit:
We already have 8 bytes written from the two addresses and we need to write
0x0804 = 2052:
Now we have
2052 bytes written and we need to write
0x84b4 = 33972:
Using these values in our exploit with the address found earlier we get:
As expected we are given our success message, but we can actually solve this in only one write. Let’s optimize.
Since the unmodified address of
exit() stored in the GOT already starts with
0x0804 writing it again is redundant. So we can jump straight to the last part of our write,
0x84b4 = 33972:
and rebuilding our exploit with this:
We successfully used a format string with direct parameter access to overwrite an entry in the GOT using only one write and seize control of program execution. End of the format string exercises!