Librando: transparent code randomization for just-in-time compilers

  • Authors:
  • Andrei Homescu;Stefan Brunthaler;Per Larsen;Michael Franz

  • Affiliations:
  • University of California, Irvine, Irvine, California, USA;University of California, Irvine, Irvine, California, USA;University of California, Irvine, Irvine, California, USA;University of California, Irvine, Irvine, California, USA

  • Venue:
  • Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security
  • Year:
  • 2013

Quantified Score

Hi-index 0.00

Visualization

Abstract

Just-in-time compilers (JITs) are here to stay. Unfortunately, they also provide new capabilities to cyber attackers, namely the ability to supply input programs (in languages such as JavaScript) that will then be compiled to executable code. Once this code is placed and marked as executable, it can then be leveraged by the attacker. Randomization techniques such as constant blinding raise the cost to the attacker, but they significantly add to the burden of implementing a JIT. There are a great many JITs in use today, but not even all of the most commonly used ones randomize their outputs. We present librando, the first comprehensive technique to harden JIT compilers in a completely generic manner by randomizing their output transparently ex post facto. We implement this approach as a system-wide service that can simultaneously harden multiple running JITs. It hooks into the memory protections of the target OS and randomizes newly generated code on the fly when marked as executable. In order to provide "black box" JIT hardening, librando needs to be extremely conservative. For example, it completely preserves the contents of the calling stack, presenting each JIT with the illusion that it is executing its own generated code. Yet in spite of the heavy lifting that librando performs behind the scenes, the performance impact is surprisingly low. For Java (HotSpot), we measured slowdowns by a factor of 1.15x, and for compute-intensive JavaScript (V8) benchmarks, a slowdown of 3.5x. For many applications, this overhead is low enough to be practical for general use today.