How do I even pwn anything? Part 8— Bypassing ASLR by “guessing” randomness.
Explore how to perform Linux Binary Exploitation from Capture-the-Flag (CTF) competitions.
Course Link
You can find all the files required for the exercises on GitHub.
Defeating ASLR
As we seen in part 4, Address Space Layout Randomisation (ASLR) randomly arranges the address space positions of key data areas such as the stack and LIBC.
Standard C Library
The Standard C Library (LIBC) is a library of standard functions and is usually referring to the GNU implementation.
Have you ever wondered how the program can run functions like printf
or fgets
without compiling the function into the binary itself? The binary uses a combination of the PLT and GOT (more on that later) to get the address of each function.
Understanding “Randomness”
Alright, to defeat ASLR, we must first understand that the randomness provided by ASLR is not truly random, and we can see why in the following example.
int main() {
puts("Some leaks for you");
printf("PRINTF@LIBC: %p\n", printf);
printf("PUTS@LIBC: %p\n", puts);
}
Now let’s look at the output! Notice how the pink section always remain the same and how the green section is the only parts where ASLR is affecting?
Ok, now that we know that the last 3 nibbles (the pink section) remains the same, what about the other 3 nibbles (green section)? Let’s do a little math to calculate the distance between the address in printf
and puts
.
We can see that the distance is the same, so it does not matter what ASLR does, because if we figure out the address of one function in LIBC, we can use a little math to retrieve the address of every single function in LIBC. This renders ASLR useless.
Do note that although the relative offsets between each symbol in LIBC is constant, it differs from different version of LIBC. However, we can also use that to our advantage.
If we can leak 2 or more symbols’ addresses in LIBC, we can essentially calculate which LIBC version the binary is using. This can be done with https://libc.rip
Process Linkage Table & Global Offset Table
Have you ever wondered how the binary is able to get the addresses of each function in LIBC? This is done using the PLT and GOT!
The Process Linkage Table (PLT) is used to call external functions whose address isn’t known at the time of linking.
The Global Offset Table (GOT) maps symbols in programming code to their corresponding absolute memory address. It’s loaded each time the program starts.
What this means is that the PLT is a table in memory that acts as pointer to the addresses on the GOT. The GOT then points to the addresses on LIBC itself.
Therefore, to leak the address of the function in LIBC, we just need to print the address at the location of the GOT. To do this, we will employ this technique called Ret2PLT, which will use the printf or puts function to leak addresses from LIBC!