Sunday, April 27, 2014


Prerequisite Reading:
Previous “Attacking V-Table Pointers” article
The web browser is a war zone. We continue to see the latest and most cutting edge research, mitigation technologies, and exploitation techniques in popular web browsers such as Internet Explorer. One advanced mitigation technology in particular is VTGuard, a run-time security check introduced in Internet Explorer 10. VTGuard verifies VTable pointers before calling into them in an effort to mitigate Use-After-Free Exploitation.
VTGuard relies on a secret cookie which should not be known by the attacker who is redirecting the VTable call. This secret cookie varies with the ASLR load address of the DLL in which the object’s VTable is implemented. Although the actual check occurs dynamically at runtime, the checking code is emitted by the compiler at compile-time, implying that the original source code needs to be modified to take advantage of this mitigation.
Below is the disassembly of a VTGuard cookie check before a virtual function call:
mov     eax,dword ptr [ebx] //ebx is a pointer to our CElement object. Now eax has a pointer to the VTable.
cmp dword ptr [eax+308h],offset MSHTML!__vtguard (728d76ee) //we check a cookie at the end of the VTable before we trust it to be a true VTable
jne     MSHTML!CElement::fireEvent+0x189 (7284c30f) //if its not, bail
mov     ecx,ebx //else, store this * into ECX as per C++ thiscall convention
call    dword ptr [eax+150h] //call into the VTable pointer
Assuming object d is an instance of a class that inherits from class B1, below is a depiction of how object d would be laid out in memory, with VTGuard in place.
VTable with VTGuard in place

Due to the difficulty of finding and removing all Use-After-Free vulnerabilities, VTGuard has its place as a strategic mitigation for increasing the difficulty of exploiting such vulnerabilities. Even if the attacker is able to reallocate the heap hole in a Use-After-Free vulnerability and craft a fake VTable (see prerequisite reading), VTGuard would still need to be bypassed.