Exploit Mitigations and Protections

ASLR

Randomizes memory addresses (but not the addresses of instructions).

Stack Canaries/Stack cookies

In a function, a stack canary is an 8-byte (or 64-bit, and 4-byte on 32-bit) value that is placed at the end of the stack. Then, at the end of the function, before the return, a check is made to determine if the canary still has the same value. If not, it’s determined that stack smashing has occurred.

It stops the function from returning, but might not protect from other side effects of the stack being overwritten.

However, note that compiler developers know about buffer overflows, so usually buffers are placed below local variables, and as close to the stack canary as possible, to prevent the variables from being overwritten.

Also note that the canary starts with a NULL byte. This is because functions like strcpy can’t write NULL bytes, and so you cannot overwrite the canary with those functions.

However, on 32 bit it’s a NULL byte and 3 more bytes, which is able to produce 16 million total random values. Depending on how the program is run, you can try to exploit it 16 million times, and on one of those tries, you might be able to get the correct stack canary by chance.

Non-Executable Memory/DEP

It’s when CPUs make memory regions, such as the stack and the heap nonexecutable. This is done by either the NX bit, or if the cpu doesn’t support it, then it’s emulated via memory segmentation.

PIE/Position Independent Executable

PIE/PIC makes it so that the addresses of the bytecode is not the same between executions. If it’s not enabled, then the location of main() is always the same, for example.

RELRO

Since the Global Offset Table and Process Linkage Table contain function pointers, which are dereferenced to call those functions, then being able to write to it will lead to arbitrary code execution.

There is a mitigation for this. Enter relocations read-only, or RELRO. It in fact has two levels of protection: partial and full RELRO.

Partial RELRO

During compilation, enabled with -Wl,-z,relro

  • Maps the .got section as read-only, but not .got.plt

  • Rearranges sections to reduce the likelihood of global variables overflowing into control structures.

Full RELRO

During compilation, enabled with -Wl,-z,relro,-z,now

Does the steps of Partial RELRO, plus:

  • Causes the linker to resolve all symbols at link time (before starting execution) and then remove write permissions from .got.

  • .got.plt is merged into .got with full RELRO, so you won’t see this section name.

Only full RELRO protects against overwriting function pointers in .got.plt. It works by causing the linker to immediately look up every symbol in the PLT and update the addresses, then mprotect the page to no longer be writable.

Last updated