9. Bypassing ASLR/NX with GOT Overwrite
Bypassing ASLR/NX with GOT Overwrite
In this section, we will take a closer look at the Global Offset Table. In the previous section, we learnt how to use jumping to the PLT stubs as a technique to reuse functions in libc. When jumping to PLT, the GOT entry for that corresponding function acted as a malleable space where the dynamic address would be held. We shall exploit that malleability.
Now, let's depart from the standard paradigm of stack overflows for the moment. We shall begin looking at vulnerable programs that allow for write-what-where primitives, albeit in a limited fashion.
Our first simple example is the following:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
struct record {
char name[24];
char * album;
};
int main() {
// Print Title
puts("This is a Jukebox");
// Create the struct record
struct record now_playing;
strcpy(now_playing.name, "Simple Minds");
now_playing.album = (char *) malloc(sizeof(char) * 24);
strcpy(now_playing.album, "Breakfast");
printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
// Read some user data
read(0, now_playing.name, 28);
printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
// Overwrite the album
read(0, now_playing.album, 4);
printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
// Print the name again
puts(now_playing.name);
}The program is vulnerable in two ways:
It provides an information leak opportunity when the
now_playing.albumpointer is overwritten and the album name is printed.It provides a write what where primitive when the
now_playing.albumpointer is overwritten and input is provided to the second prompt.
Running the binary:
It's a little screwy but nothing that fancy yet. Let's begin by trying to achieve the first vulnerable condition (arbitrary read). First, we can take an easy to spot target to leak. We can use the "This is a Jukebox" string. First, we need to figure out its address.
Now, here's a skeleton exploit that will demonstrate the leaking of that string.
Testing it out:
See the "(This is a Jukebox)"? That means it worked. Now, what we are most interested in are mostly pointers. So let's make a small addition that would parse the leak and transform it into a nice number for us.
Running it:
Awesome, now we can begin thinking about our exploit.
GOT Overwrite Strategy
At the moment, we do not have a target to leak and to overwrite. We must be careful to pick a suitable one because the information leak and arbitrary write has to be performed on the same address. Additionally, the write has to result in EIP control at some point of the program's execution since we do not have that yet.
If we take a look at the source code again, the following function is called last:
Interestingly, this is perfect for our uses. If we leak the address of puts in libc, we can calculate the address of the libc base and subsequently, the address of the system function. Also, once we have that, we can write the address of the system function into the puts@got entry so that when this final line executes, it will actually execute:
Which means that system will be called with a parameter that we control! How convenient!
Writing the Exploit
First, let's see if we can leak the address of puts@got. First, we need the address.
Now, we can modify our earlier iterations of the exploit.
Running the script gives us a sanity check that we are reading the right thing.
Now, let's try and get EIP control. This should be as simple as sending four bytes.
It works, the program crashed at 0xdeadc0de.
Let's gather our offsets and we can write our final exploit script.
Final exploit script:
Getting our shell:
Exercises
Ex 10.1: Event 1
After the mistakes of the previous Event, Kaizen has decided to secure his system. Can you find a way to exploit the new binary?
It was compiled with a stack canary.
gcc -m32 -znoexecstack -o ./build/2_event1 ./src/2_event1.c
The binary can be found here and the source can be found here. The remote target is nc localhost 1902.
The solution script may be found here.
Last updated
Was this helpful?