Mitigations

ASLR

ASLR (Address Space Layout Randomization) is an exploit mitigation by the OS kernel which essentially makes it so that every time a binary is executed, any libraries used by the program are loaded into a different memory address.

This effectively prevents us from hardcoding addresses to gadgets or functions within our exploit code.

PIE

PIE (Position Independent Executable) is an exploit mitigation put in place by the compiler and essentially means that every time the program is executed, the program itself gets loaded into a different memory address. The base addresses of the program are different every time, but the offsets of all the addresses are the same.

Much like ASLR, PIE also prevents us from hardcoding addresses within our exploit code.

DEP / NX

DEP (Data Execution Prevention), also known as NX (No eXecute), prevents certain blocks of memory from being executable.

This mitigation prevents shellcode that gets written on the stack from being executed.

Stack Canary

A stack canary is a randomized value which protects against stack smashing. In areas of the program at high risk of buffer overflow attacks, a stack canary is initialized during the function prologue and checked again for tampering during the function epilogue. If the canary was overwritten, then the program will terminate at that point.

Stack canaries prevent trivial buffer overflow attacks.

Bypass

ASLR

There are multiple ways to bypass ASLR.

One of the simpler ways to bypass ASLR is to leak the memory address of a libc function, such as system. In order to use this strategy to defeat ASLR, we would need to calculate the base address of libc based on the address that we leaked and the version of libc that the target is using.

Another way to defeat ASLR is to leverage the procedural linkage table (PLT). If the program is contains a PLT entry for a libc function like system@plt, then we can essentially use that memory address to call the libc system function without knowing the base address of libc.

PIE

Similar to ASLR, in order to defeat it, we will need to leak memory addresses.

If we are able to leak the address of a function in the program, like main, then we have essentially defeated PIE and are able to determine the addresses of all other functions in the program based off of the base address.

DEP / NX

DEP/NX can be defeated with return-oriented-programming (ROP) and using existing gadgets in the binary. Since NX makes it impossible to execute newly injected shellcode on the stack, the next logical step is to look at what we can reuse within the program.

By building a ROPchain with pre-existing gadgets within the program, we can defeat NX and execute code.

Stack Canary

Because stack canaries are placed on the stack, we are able to defeat stack canaries in many cases by using a format string exploit to print out the canary at runtime. The canary is randomized, but the placement of the canary on the stack is not, so if we are able to determine the location of the canary on the stack and we can leverage a format string exploit, we have a reliable way to determine the stack canary. Stack canaries can be recognized visually as they are fairly random and always end in 00.

Once we obtain the canary value, we can add it to our payload so that the stack canary check in the function epilogue does not fail.