Exploiting and Protecting Dynamic Code Generation

NDSS 2015,

Chengyu Song , Chao Zhang , Tielei Wang , Wenke Lee , David Melski .

Abstract

Many mechanisms have been proposed and de- ployed to prevent exploits against software vulnerabilities. Among them, W⊕X is one of the most effective and efficient. W⊕X prevents memory pages from being simultaneously writable and executable, rendering the decades old shellcode injection technique infeasible.

In this paper, we demonstrate that the traditional shellcode injection attack can be revived through a code cache injection technique. Specifically, dynamic code generation, a technique widely used in just-in-time (JIT) compilation and dynamic binary translation (DBT), generates and modifies code on the fly in order to promote performance or security. The dynamically generated code fragments are stored in a code cache, which is writable and executable either at the same time or alternately, resulting in an opportunity for exploitation. This threat is especially realistic when the generated code is multi-threaded, because switching between writable and executable leaves a time window for exploitation. To illustrate this threat, we have crafted a proof- of-concept exploit against modern browsers that support Web Workers.

To mitigate this code cache injection threat, we propose a new dynamic code generation architecture. This new architecture relocates the dynamic code generator to a separate process, in which the code cache is writable. In the original process where the generated code executes, the code cache remains read- only. The code cache is synchronized across the writing process and the execution process through shared memory. Interaction between the code generator and the generated code is handled transparently through remote procedure calls (RPC). We have ported the Google V8 JavaScript engine and the Strata DBT to this new architecture. Our implementation experience showed that the engineering effort for porting to this new architecture is minimal. Evaluation of our prototype implementation showed that this new architecture can defeat the code cache injection attack with small performance overhead.