Authors: Nicholas Mosier, Pete Johson
While a Turing-complete set of ROP gadgets can easily be found in libc, many existing ROP compilers are not Turing-complete or do not include essential programming language constructs, such as subroutine calls.
ROPC is a proof-of-concept ROP compiler for 64-bit x86_64 architectures that achieves Turing-completeness by maintaining a second, shellcode-accessible stack, which most notably makes possible subroutine calls within the exploit itself. Turing-completeness allows shellcode to avoid suspicious behavior such as calling system(3) and to return control to the target process.
As input, ROPC accepts (i) source files written in so-called ROPC-IR, (ii) rules for translating ROPC-IR instructions to sequences of gadget addresses, and (iii) static configuration parameters about the victim process. As output, it produces a two-stage shellcode (a sequence of gadget return addresses) that can be injected onto the target process’ stack.
The distinguishing features of ROPC is its emulation of a second stack available to the ROP shellcode and its consequent support for nondestructive invocation of library and system calls (with variable parameters) as well as shellcode subroutine calls.