Chapter 36 Key Takeaways: Exploit Mitigations
-
Exploit mitigations are an arms race: each mitigation closes one attack vector and forces attackers to find another. Understanding this history explains why each mitigation is designed the way it is and why multiple mitigations together are far more effective than any one alone.
-
Stack canaries are a random value between locals and the return address, stored at
rbp-8: the compiler inserts two instructions in the prologue (mov rax, [fs:0x28]; mov [rbp-8], rax) and three in the epilogue (mov rax, [rbp-8]; xor rax, [fs:0x28]; jne __stack_chk_fail). The canary is read from thread-local storage, is random per-process, and has a null low byte. -
The canary's null low byte prevents string-function leaks:
strcpy,puts, and similar functions stop at null bytes. Placing a null byte at the low end of the canary means string-based reads cannot extract the full canary value — they terminate at the null. -
NX/DEP marks memory pages non-executable via bit 63 of the page table entry: the CPU raises a fault when execution reaches a non-executable page. This killed classic shellcode injection — writing shellcode to the stack and returning into it no longer works. It forced the development of ROP (Chapter 37).
-
ASLR randomizes stack, heap, and library base addresses but NOT the executable (unless PIE is enabled): without PIE, gadgets in the executable itself are at predictable addresses even with full ASLR. Always compile production binaries with
-pie -fPIE. -
Full RELRO makes the GOT completely read-only by resolving all symbols at startup: Partial RELRO (just
-z relro) protects the non-PLT GOT but leaves PLT entries writable. Full RELRO (-z relro -z now) resolves everything at startup and marks the entire GOT read-only. Use Full RELRO for production binaries. -
CET's Shadow Stack (SHSTK) is hardware-enforced and software-inaccessible: shadow stack pages have a special page attribute that causes general protection faults on software writes. Only the CPU itself (via CALL/RET) can modify shadow stack contents. No software vulnerability can forge a shadow stack return address without a hardware-level flaw.
-
CET's IBT (Indirect Branch Tracking) requires
ENDBR64at every valid indirect call target: functions that can be called indirectly must begin withendbr64(F3 0F 1E FA). On non-CET CPUs, this decodes as a harmlessREP NOP. This eliminates most ROP gadgets (which do not begin withENDBR64) as valid indirect call targets. -
ENDBR64and SHSTK address different attack vectors: SHSTK prevents forging return addresses (defeats ROP that usesretgadgets); IBT prevents forging indirect call/jump targets (defeats JOP, function pointer corruption). Together they cover the full indirect control flow attack surface. -
checksecis the standard tool for auditing binary security features: runchecksec --file=binaryto see RELRO level, canary presence, NX, PIE, CET, and RPATH/RUNPATH issues. Automate it in CI/CD pipelines to prevent security regressions. -
A hardened binary has all five: Full RELRO + Canary + NX + PIE/ASLR + CET. Each addresses a different attack path; omitting any one creates an available bypass. The incremental cost is minimal (slight startup overhead for Full RELRO; negligible for canary and NX; small code size increase for ENDBR64 markers).
-
Canary bypass requires an information leak: the only way to pass a canary check with a forged return address is to know the canary value. Format string vulnerabilities and out-of-bounds reads can leak it. This is why format string bugs are often used as the first step in a multi-stage exploit chain.
-
ASLR bypass requires an address leak: ASLR is defeated by any vulnerability that reveals a code or data address. One leaked
libcaddress reveals the entire libc base (leaked_address - known_offset = libc_base). This is why information leak vulnerabilities are paired with exploitation primitives. -
Defense in depth makes exploitation chains longer and more fragile: each mitigation the attacker must bypass adds another step and another opportunity to fail. A 5-step exploit chain that must succeed at each step is exponentially less reliable than a 1-step chain. Mitigations do not need to be unbreakable — they need to make exploitation impractical in practice.
-
CET represents a qualitative improvement over previous mitigations: canaries can be bypassed by leaking and reusing them; ASLR can be bypassed by information leaks. SHSTK cannot be bypassed by any software vulnerability — it requires a hardware flaw. This is a fundamentally different class of protection, though defense in depth with other mitigations remains essential.