|Crane, Stephen; Liebchen, Christopher; Homescu, Andrei; Davi, Lucas; Larsen, Per; Sadeghi, Ahmad-Reza; Brunthaler, Stefan; Franz, Michael
|Detecting and preventing exploitation of memory corruption vulnerabilities is highly challenging. Until now, no countermeasure has been able to fully prevent sophisticated exploitation techniques, such as return-oriented programming (ROP). Recent control-flow integrity (CFI) defenses from Google and Microsoft can be bypassed by constructing a ROP payload that adheres to the control-flow constraints or by exploiting implementation flaws. Microsoft's EMET has less overhead than full CFI, but offers less protection in return, and can be bypassed. Probabilistic countermeasures based on memory layout randomization (such as ASLR) are already in widespread use. However, the Pwn2own competitions have repeatedly demonstrated that attackers can bypass code randomization using memory leaks in browsers.
To reduce the impact of memory disclosure, recent defenses utilize execute-only memory. In this work we show that execute-only memory is insufficient and that these solutions can still be bypassed. In particular, we show how to determine the code layout by analyzing pointers in the heap and on the stack without ever reading the code.
On the defensive side, we build a comprehensive yet practical defense called Readactor that counters both direct reading of code and indirect layout disclosure through analysis of code pointers. We employ a thin hypervisor and a kernel patch to utilize true hardware execute-only memory, and prevent direct reading of code in Linux processes. We hide all code pointers in readable memory using a patched version of the LLVM compiler. We deploy a number of techniques to break ROP gadget chains and disorient the adversary. Specifically, we hide code pointers by converting them into direct jumps stored in execute-only memory to prevent indirect layout disclosure.