DEP & ASLR Bypass

In this article, we’re going to be looking at a method of bypassing non-executable stack protection (NX/DEP) and Address Space Layout Randomisation on 32-bit Linux.

Below is the sample application we will be exploiting:

Compile the code with:

Running the program in our debugging environment (gdb-peda) we can see the program encounters a segmentation fault if more than 500 characters are entered:

We can see the instruction pointer (EIP) has been overwritten with the “A” characters we generated.

Checking the memory protection mechanisms enabled on the binary shows that NX is active. Because of this, we will be unable to inject shellcode onto the stack.

With GDB-Peda, we can locate the offset required to overwrite the instruction pointer:

We now know the instruction pointer (EIP) can be overwritten after 36 bytes. Let’s verify that using a Python script:

The EIP register has been overwritten with out “B” characters, which is represented in hex as 0x42.

Since DEP is enabled on the executable, we won’t be able to inject arbitrary code onto the stack. The solution to this is return orientated programming (ROP). Essentially we can execute instructions which already exist within the application.

However, Address Space Layout Randomization (ASLR) will hamper this effort since memory addresses will be randomized each time the application starts.

So first, we’re going to need to attempt to leak a pointer to an existing function. By leaking a pointer, we should able able to determine the current random base pointer address. Below illustrates how the memory addresses are being randomized each time the application starts:

Stage 1: Pointer Leakage

To leak a pointer, we need to know three things;

  1. The address of the puts function procedure linkage table (PLT) value.
  2. A pointer to the programs main function. This is needed since if the application terminates the ASLR base address will be randomised again.
  3. The puts function address in the Global Offset Table (GOT)

We can get these values one and two using GDB:

To get the GOT address, run the application in GDB and ctrl+c to terminate it’s execution. This is required since the GOT address will only be resolved when the PLT stub has first ran.

The below Python code implements stage 1 of the attack. The EIP register will be overwritten with the puts@PLT pointer. The other values will be read from the stack as arguments to this function. Main acts as the functions return address. The puts@GOT pointer will be read from memory. This resides within the libc library.

Running the code shows the puts@glibc address as 0xb75aeca0. This value will change each time the application is restarted.

Stage 2: Return2Libc ROP Chain

We can determine the base address of LibC by subtracting 0005fca0 from the leaked puts pointer:

Knowing the randomised base address, we can then call the system function with the parameter of “/bin/sh”.

The final exploit looks like this: