NDSS Home

Author(s): Chengyu Song, Chao Zhang, Tielei Wang, Wenke Lee, David Melski

Download: Paper (PDF)

Date: 7 Feb 2015

Document Type: Briefing Papers

Additional Documents: Slides

Associated Event: NDSS Symposium 2015

Abstract:

Many mechanisms have been proposed and deployed to prevent exploits against software vulnerabilities. One of the most effective and efficient is W xor X that prevents memory pages from being writable and executable at the same time. This enforcement completely renders 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 code cache, which is writable and executable either at the same time or alternately, resulting in an opportunity for exploit. This threat is especially realistic when the generated code is multi-threaded, because simply switching between writable and executable leaves a time window for exploit. To illustrate this threat, we have crafted a proof-of-concept exploit against modern browsers that support Web Worker. 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 can be modified. At the same time, in the original process where the generated code is executed, the code cache remains read-only. The code cache is synchronized between the writing process and the execution process through shared memory. Any interaction between the code generator and the generated code is handled transparently through remote-procedure call (RPC). We have ported Google V8 JavaScript engine and Strata DBT to this new architecture. Our implementation experience showed that the engineering effort for porting to this new architecture is very small. Evaluation of our prototype implementation showed that this new architecture can defeat the code cache injection attack with small performance overhead.