How do I even pwn anything? Part 8— Bypassing ASLR by “guessing” randomness.

Daryl 🥖
3 min readMay 28, 2024

Explore how to perform Linux Binary Exploitation from Capture-the-Flag (CTF) competitions.

Click here for part 7!

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?

Addresses of functions in LIBC

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.

Distance between 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

Calculating LIBC version with offsets

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.

Process Linkage Table (PLT)
Global Offset Table (GOT)

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!

--

--