BOOT CHAIN LAB
Lab 10 · detection engineering

The exploit that injects nothing.

When defenders made memory non-executable (DEP / W^X), injected shellcode stopped running — so attackers stopped injecting. Return- and jump-oriented programming build the payload out of code that's already there: tiny fragments ending in ret or jmp, chained into a program by a crafted stack. There's no sled (Lab 8), no new executable page (Lab 6), no foreign file (Lab 9) — nothing for a byte scanner to see. So the detection moves to the one thing the attack can't fake: control flow that doesn't obey the rules.

01 — no payload, only misuse

Reuse leaves a different mark

A normal program returns to the instruction right after a call — that's the contract of a function return. A ROP chain ignores that contract: it returns into the middle of existing functions, to short sequences that do one small thing and ret again, walking down a stack the attacker controls. The bytes are all legitimate, signed, on-disk code. What's illegitimate is the order they run in, and that disorder is measurable.

return provenanceA real return lands on an address immediately preceded by a call. A gadget return lands mid-function, on an address no call ever targets. Check each return's target against that rule.
shadow stackKeep a second, protected copy of every return address as calls happen. On each ret, compare. A ROP chain's returns were never pushed by a real call — so they diverge from the shadow copy. This is now hardware (Intel CET).
the stack pivotTo drive the chain, the exploit first points the stack pointer at attacker-controlled memory — a pivot from the real stack into a heap/buffer region. A stack pointer suddenly outside the thread's stack bounds is a loud, early tell.
02 — verify the control flow

Catch the chain by its returns

A captured return trace from a crashing process. Verify it: each return is checked for call-preceded provenance and against the shadow stack, and the stack pointer is checked against the thread's real stack bounds. The genuine frames pass; the chain lights up.

CPU return addresses

shadow stack (protected)

Verify to check return provenance, the shadow stack, and the stack pointer.
03 — who enforces it now

The checks became silicon

Software ROP detection was noisy and slow, so control-flow integrity moved down into the hardware and the loader. You don't hand-roll this in a SOC — you verify it's on, and you alert when a process trips it:

# the enforcement layers, newest first
Intel CET        shadow stack (SS) + indirect-branch tracking (IBT)   ; ret/jmp targets enforced in HW
ARM   PAC / BTI  pointer authentication + branch-target identification ; Apple silicon
MS    CFG / XFG  control-flow guard — valid indirect-call targets only
OS    ACG + stack-pivot checks   ; arbitrary-code-guard, EMET/WDEG heritage

# the SOC job: confirm it's enabled, and treat a CFI fault as an exploit signal
a CET #CP (control-protection) fault  ->  ROP/JOP attempt, not a normal crash
04 — the hard part

JOP doesn't even use ret

05 — provenance & citations

Where this comes from

the technique H. Shacham (2007), “The Geometry of Innocent Flesh on the Bone: Return-into-libc without Function Calls,” ACM CCS — the ROP paper.
Checkoway et al. (2010), “Return-Oriented Programming without Returns” — JOP.
this lab: github.com/Mik3XC/BlueTeamLab
the defenses Intel CET — shadow stack + IBT.
ARM — Pointer Authentication (PAC) + Branch Target Identification (BTI).
Microsoft — Control Flow Guard (CFG/XFG), Arbitrary Code Guard.
MITRE ATT&CK — Exploitation techniques; the pivot & RWX aftermath map to Labs 6 & 7.

Next: Lab 11 — macOS persistence: Lab 1's story on your own platform, LaunchAgents to TCC, osquery-driven.