A program's source code is full of indirect jumps: function pointers, virtual-method dispatch tables, and the humble return instruction. At compile time these jumps have obvious, intended targets. At run time an attacker who controls a corrupted pointer can send the jump anywhere in memory â including into the middle of a sequence of existing instructions that, chained together, do something malicious. No new shellcode needed.
This class of attack â return-oriented programming (ROP) and its cousins â became the dominant exploitation technique after hardware and OS defenses made injecting new executable code expensive. The attacker's payload is assembled entirely from gadgets: short instruction sequences already present in the binary, each ending with a ret or indirect jmp.
Control-Flow Integrity (CFI) answers with a simple invariant: every indirect branch must land on a target that the original program could legitimately reach. The compiler computes a set of valid targets for each call site and inserts a lightweight check before each indirect jump. If the redirected target is not in the approved set, the process is terminated before the gadget chain can do any damage.
The idea was formalized by Abadi, Budiu, Erlingsson and Ligatti in their landmark 2005 paper. Since then, LLVM, GCC, Microsoft's Control Flow Guard, and ARM's Branch Target Identification have turned CFI from a research curiosity into a production-grade defense deployed on billions of devices.
Comments
Loading comments...