This paper is published in NDSS 2018. In this paper, the author proposed the concept of Object Type Integrity as an orthogonal policy as CFI to protect the target written in C++.
Virtual function callsite in victim application has become a popular target for hijacking control flow. To prevent such control flow hijacking, multiple CFI mitigations have been proposed in academic papers. Different from CFI, OTI does not verify the validity of the transfer target but verifies that the correct object type is used (the one assigned by the constructor when the object was allocated).
OTI guarantees that each C++ object has the correct type. To achieve this, CFIXX identifies legitimate (compiler inserted) virtual table pointer assignments. These are recorded as the ground truth type of the objects. CFIXX then protects the integrity of these assignments, ensuring that an attacker cannot modify them. The integrity protection is accomplished by recording the original virtual table pointer assignment in a protected metadata table.
OTI enforcement is based on the observation that only constructors can legitimately write virtual table pointers in C++ and any other write is invalid.
Based on this, CFIXX guarantees virtual table pointer integrity through a
two part enforcement mechanism which utilizes a metadata table: (i) recording the correct virtual table pointer in the metadata table, and (ii) using our recorded virtual table pointer for dynamic dispatch on the object. For part (i), CFIXX records the virtual table pointer assigned to the object in the metadata table during this initial assignment. For part (ii), CFIXX looks up the correct virtual table pointer for the object in the metadata table during dynamic dispatch, instead of using the (possibly attacker corrupted) virtual table pointer in the object.
CFIXX is implemented on top of LLVM 3.9.1, and has three components. The first part is creating, and protecting, the data structure for our metadata. Secondly, CFIXX creates metadata entries each time the compiler assigns a virtual table to a polymorphic object. Finally, CFIXX modifies the dynamic dispatch mechanism to leverage the recorded virtual table pointer for an object.
The metadata is stored in a two level lookup table. To find the correct entry, the pointer is split into two parts. The high order bits are the index in the top level table. Entries in the top level table are pointers to the second level tables. The low order bits, 20 in the example, are the index in the second level table, which stores the correct virtual table pointer for the object.
Attacking model of CFIXX assumes a strong attacker who can perform arbitrary reads and writes. Therefore, CFIXX must protect the metadata from modification by an adversary.
CFIXX leverages MPX bounds checks to prevent unauthorized writes to our metadata, by dividing memory writes into two categories: those added by CFIXX to maintain the metadata and all other writes.
The MPX hardware extension is designed to provide hardware support for verifying that a pointer is in bounds for memory object accesses. To do so, MPX introduces four new 128 bit registers for storing upper and lower bounds.
CFIXX instruments the virtual calls to use the virtual table pointer from our metadata, as is illustrated with C pseudo code in Figure below.
From the Figure above, we can see that the metadata of virtual function pointer is fetched via the address of allocated object.
The author evaluated CFIXX on the SPEC CPU2006 compiler benchmarks, as well as on Chromium.
For C++ benchmarks in SPEC CPU2006 compiled with CFIXX. CFIXX has 2.22% overhead without MPX protecting the metadata, and 4.98% with full MPX protection.
To evaluate CFIXX’s robustness and impact on real world code, the author recompiled the Chromium browser on FreeBSD.
In this paper, the author proposed a novel idea on Object Type Integrity (OTI), which can be combined with other CFI strategy to enforce the forward edge in Control Flow Graph.