Seminar | October 21 | 1-2 p.m. | Soda Hall, Wozniak Lounge
Hovav Shacham, University of California, San Diego
Return-oriented programming is an attack technique that induces arbitrary behavior in the compromised program without injecting new code into its address space. A return-oriented attack combines short sequences of instructions from a target program’s executable image into a Turing-complete set of combinators, called “gadgets,” from which any desired functionality can be synthesized. The addresses of the desired sequences are arranged on the program’s stack, which the attacker rewrites using a buffer overflow or other memory vulnerability. Each instruction sequence used ends in a “return” instruction; this instruction transfers control from the currently executing sequence to the next (and gives the technique its name). Return-oriented programming was introduced in 2007 as a way of defeating the Data Execution Prevention defense that Microsoft implemented in Windows XP SP2. The original attack was specific to the x86 processor and largely manual.
In this talk, we survey the research on return-oriented programming since its introduction, showing that the threat is both more general and more acute. Defenses that prevent code injection (without also protecting control flow integrity) are useless against return-oriented programming. In particular, relative to return-oriented programming, Harvard architecture machines (with separate data and program memories) are no more secure than von Neumann architecture machines (with one data-and-program memory). Return-oriented programming is applicable across a range of architectures and systems: research has demonstrated it on the x86, SPARC, Z80, PowerPC, and AVR processors; on Linux, Solaris, Windows, and embedded systems; on PCs, servers, routers, sensor network nodes, and even voting machines. Automated tools like exploit compilers and gadget-set generators can make writing return-oriented exploits as simple as writing traditional ones.