Code signing executable page of memory is signed, and instructions executed only if the signature is correct.

SEHOP checks the validity of a thread’s exception handler list before allowing any to be called.

Pointer encoding Function pointers can be encoded (using XOR or other means) within Microsoft Visual Studio and GCC. If encoded pointers are overwritten without applying the correct XOR operation first, they cause a program crash.

Stack canaries Compilers including Microsoft Visual Studio, GCC, and LLVM Clang place canaries on the stack before important values (e.g., saved eip and function pointers on the stack). The value of the canary is checked before the function returns; if it has been modified, the program crashes.

Heap protection Sanity checking within heap management code. These improvements protect against double free and heap overflows resulting in control structures being overwritten.

Relocation read-only (RELRO) The GOT, destructors, and constructors entries within the data segment can be protected through instructing the GCC linker to resolve all dynamically linked functions at runtime, and marking the entries read-only.

Format string protection Most compilers provide protection against format string attacks.

Data execution prevention (DEP) is used to mark writable areas of memory, including the stack and the heap, as non-executable. CPU can set a bit NX (no-excutable) to portions of the stack.

Address space layout randomization (ASLR) makes it difficult for an attacker to commandeer logical program flow; however, implementation flaws exist, and some libraries are compiled without ASLR support.

Bypassing DEP DEP prevents the execution of arbitrary instructions from writable areas of memory. As such, you must identify and borrow useful instructions from the executable text segment to achieve your goals. The challenge is one of identifying sequences of useful instructions that can be used to form return-oriented programming (ROP) chains. It involves looking for snippets of code called ROP gatgets within the legitimate modules of the application that execute some interesting instructions and return the execution flow. For example, if the first task of the exploit is to pop EAX we will look for a pop eax; ret in the module and we will replace EIP with its address. We can chain multiple gadgets to write an exploit. The goal is to find a memory protection API such as VirtualProtect and mark the stack as executable and then the JMP ESP. The gadgets need to be in a module that does not support ASLR and DEP.

In order to prevent this, ASLR was developed. ASLR randomizes at runtime/boot time the addresses of the structures and modules to make it difficult to guess the location of ROP gadgets.

There are a few ways to bypass ASLR:

Direct RET overwrite: Often processes with ASLR will still load non-ASLR modules, allowing you to just run your shellcode via a jmp esp.

Partial EIP overwrite: Only overwrite part of EIP, or use a reliable information disclosure in the stack to find what the real EIP should be, then use it to calculate your target. We still need a non-ASLR module for this though.

NOP spray: Create a big block of NOPs to increase chance of jump landing on legit memory. Difficult, but possible even when all modules are ASLR-enabled. Won't work if DEP is switched on though.

Bruteforce: If you can try an exploit with a vulnerability that doesn't make the program crash, you can bruteforce 256 different target addresses until it works.