Chapter 36 Exercises: Exploit Mitigations
Warm-Up Exercises
Exercise 36.1 — Mitigation identification Match each mitigation to its primary defense:
| Mitigation | Primary Defense |
|---|---|
| Stack canary | A. Prevents executing code on non-executable memory pages |
| NX/DEP | B. Prevents use of PLT GOT entries as attack vectors |
| ASLR | C. Detects overwrites between local variables and return address |
| Full RELRO | D. Makes indirect branch targets verifiable in hardware |
| CET IBT | E. Randomizes base addresses of code and data regions |
| CET SHSTK | F. Maintains hardware-protected copy of return addresses |
Exercise 36.2 — checksec output reading
Given this checksec output, answer the questions:
[*] './challenge_binary'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
RPATH: /opt/custom_libs
a) Is classic shellcode injection possible? b) Is GOT overwrite via PLT entries possible? c) Is a return address overwrite immediately useful without further steps? d) What is the easiest additional compiler flag to add that would significantly improve security? e) What concern does the RPATH entry raise?
Exercise 36.3 — Canary assembly reading Identify the canary read and check in this epilogue:
4011f0: 48 8b 45 f8 mov rax, [rbp-0x8]
4011f4: 64 48 33 04 25 xor rax, QWORD PTR fs:0x28
28 00 00 00
4011fd: 74 05 je 0x401204
4011ff: e8 xx xx xx xx call __stack_chk_fail@plt
401204: c9 leave
401205: c3 ret
a) Where is the canary stored on the stack?
b) What instruction compares the current stack value to the original?
c) What happens if the canary has been modified?
d) Why is xor used instead of cmp for the check?
Assembly Analysis Exercises
Exercise 36.4 ⭐ — Canary prologue identification Examine this function prologue and identify all security-related instructions:
0000000000401196 <process_request>:
401196: f3 0f 1e fa endbr64
40119a: 55 push rbp
40119b: 48 89 e5 mov rbp,rsp
40119e: 48 83 ec 50 sub rsp,0x50
4011a2: 64 48 8b 04 25 mov rax,QWORD PTR fs:0x28
28 00 00 00
4011ab: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
4011af: 31 c0 xor eax,eax
a) Which instruction indicates CET IBT is enabled?
b) Which two instructions implement the canary read and store?
c) Why does xor eax, eax appear after the canary store?
d) Where exactly on the stack is the canary? (Express as an offset from RBP)
Exercise 36.5 — PIE vs no-PIE
Compile a simple "Hello World" program twice: once with -no-pie and once with -pie -fPIE. Run each 5 times and record the address of main. What do you observe? What does this mean for an attacker who knows the binary but not the load address?
Exercise 36.6 ⭐ — NX verification
Write the commands to:
a) Check if /usr/bin/cat has NX enabled
b) Check if a running process's stack is executable (/proc/PID/maps)
c) Compile a program with NX disabled (for testing only) and verify with checksec
d) What does the difference between r-xp and rwxp in /proc/maps mean?
Mitigation Reasoning Exercises
Exercise 36.7 — Canary bypass requirements A server has a stack canary and is running with ASLR. The server also has a format string vulnerability in its logging function.
a) Explain step-by-step how a format string vulnerability could be used to leak the canary value b) Once the canary is known, what other information is needed to exploit the stack overflow? c) How many exploit primitives (information leaks + writes) would a full exploitation chain require? d) How does Full RELRO affect the options available once the canary is known?
Exercise 36.8 — ASLR entropy calculation a) On a 64-bit Linux system with ASLR fully enabled, the stack base has approximately 24 bits of randomness, aligned to 4096-byte page boundaries. How many possible stack base addresses exist? b) A 32-bit x86 Linux system has approximately 8 bits of stack randomness. How many possible addresses? Is brute-force feasible? c) What is an "information leak" in the context of ASLR bypass, and why does one leaked address often break all of ASLR for a library?
Exercise 36.9 ⭐ — RELRO deep dive
Consider a call to puts in a PIE-compiled binary with Full RELRO:
a) Before the first call to puts, what does the GOT entry for puts contain?
b) After the first call with Full RELRO (where all symbols are resolved at startup), what does the GOT entry contain?
c) Can an attacker overwrite the puts GOT entry with Full RELRO? Why or why not?
d) If Full RELRO prevents GOT overwrites, where might an attacker look for writable function pointers instead?
CET and Modern Mitigations
Exercise 36.10 — ENDBR64 identification Given this disassembly, determine whether CET IBT is enabled:
; Binary A:
00401160 <vulnerable>:
401160: 55 push rbp
401161: 48 89 e5 mov rbp,rsp
; ...
; Binary B:
00401160 <protected>:
401160: f3 0f 1e fa endbr64
401164: 55 push rbp
401165: 48 89 e5 mov rbp,rsp
; ...
a) Which binary has CET IBT enabled?
b) What encoding is endbr64? What does it decode to on older CPUs?
c) Why does endbr64 at a function entry not protect against ROP gadgets within the function?
d) Why does SHSTK (not IBT) address the ROP problem?
Exercise 36.11 ⭐ — Shadow stack mechanics Trace through the shadow stack behavior for the following call sequence:
main() calls foo() at return address 0x401234
foo() calls bar() at return address 0x401268
bar() returns
foo() returns
a) Show the shadow stack contents after each CALL and before each RET
b) Now assume an attacker overwrites the return address in foo's stack frame with 0xdeadbeef. What happens when foo's ret executes with CET SHSTK enabled?
c) Why is SHSTK superior to stack canaries for preventing return address corruption?
Exercise 36.12 — CET adoption and limitations Research (or reason about) these questions about CET's real-world deployment:
a) CET SHSTK requires that CALL always pushes to the shadow stack and RET always checks it. What happens to code that uses ret for purposes other than returning from a call (e.g., old-style computed jumps)?
b) What happens with setjmp/longjmp if SHSTK is enabled? How is this handled?
c) Why does CET IBT require all valid indirect call targets to be marked with endbr64? What challenges does this create for JIT compilers?
Compiler and Build System Exercises
Exercise 36.13 ⭐ — Compile with mitigations Compile this program with all recommended security mitigations and verify with checksec:
#include <stdio.h>
#include <string.h>
void greet(const char *name) {
char buf[64];
snprintf(buf, sizeof(buf), "Hello, %s!", name);
puts(buf);
}
int main(int argc, char **argv) {
if (argc < 2) return 1;
greet(argv[1]);
return 0;
}
Command: gcc -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -pie -fPIE -Wl,-z,relro -Wl,-z,now -o greet greet.c
a) Run checksec --file=greet and record the output
b) Disassemble the prologue of greet to see the canary instructions
c) What would change if you added -fcf-protection=full?
Exercise 36.14 — Makefile security flags
Write a Makefile that compiles a C program with all recommended security flags. Include:
- Canary (-fstack-protector-strong)
- FORTIFY_SOURCE
- PIE
- Full RELRO
- CET (if supported: -fcf-protection=full)
- Helpful warnings (-Wall -Wextra -Wformat-security)
Exercise 36.15 — Security regression testing Describe a CI/CD pipeline check that ensures compiled binaries always have the required security features. What command would you run? What would cause it to fail?
Deep-Dive Exercises
Exercise 36.16 ⭐ — Complete mitigation analysis
You have a server binary. checksec shows:
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
The server has a known stack buffer overflow vulnerability with a format string vulnerability also present. Describe the complete theoretical exploitation chain required to achieve code execution. For each step, identify which mitigation makes it necessary.
Exercise 36.17 — TLS canary deep dive
The stack canary lives at fs:0x28 in the Thread Control Block.
a) What is the Thread Control Block (TCB), and who sets it up? b) How is the TCB set up differently for the main thread vs. created threads? c) What is the low byte of the canary always set to, and why does this matter? d) In a multi-threaded server, does each thread have its own canary value?
Exercise 36.18 — GOT and PLT walkthrough For a dynamically linked binary with Partial RELRO:
a) Describe the sequence of events on the FIRST call to malloc
b) Describe what happens on SUBSEQUENT calls to malloc
c) Draw the memory layout showing the PLT stub, the GOT entry, and their relationship
d) How would an attacker overwrite the free GOT entry to redirect it to system? What conditions are required?
Exercise 36.19 — CET microarchitecture Intel CET SHSTK is implemented partly in the CPU's microarchitecture:
a) What new memory type (page attribute) is used for shadow stack pages?
b) What happens if software tries to write to a shadow stack page with MOV [addr], rax?
c) How does the CPU save/restore the shadow stack pointer on context switches?
d) Why can't SHSTK be implemented in software (e.g., as a library check) with the same security guarantees?
Exercise 36.20 ⭐ — Defense-in-depth evaluation Rate the security of each configuration against modern exploit techniques (information-leak-assisted ROP + heap UAF). Use: Strong / Moderate / Weak.
| Configuration | Rating |
|---|---|
| No mitigations (NX disabled, no canary, no ASLR) | ? |
| NX only | ? |
| NX + Canary | ? |
| NX + Canary + ASLR | ? |
| NX + Canary + ASLR + PIE + Full RELRO | ? |
| All above + CET (IBT + SHSTK) | ? |
Explain your reasoning for each step change.