Microsoft’s June Patch Kills Potential CFG Bypass

By on

After applying Microsoft’s June patch, we noticed some interesting changes that prevent a security bypass of Windows’ Control Flow Guard (CFG). The changes are in the Shader JIT compiler of the Windows Advanced Rasterization Platform (WARP) module (d3d10warp.dll). The Shader JIT compiler could formerly be used to create a CFG bypass. CFG is known to have problems with dynamic code, such as that created by JavaScript JIT and ActionScript JIT compilers. With this update, CFG becomes more robust, and especially more resistant to bypass attacks involving JIT techniques.

WARP is a software-based rasterizer that contains a high-performance JIT code generator which can convert High-Level Shader Language byte code to optimized native machine code (SSE, x86/x64). Moreover, WARP is accessible in the context of the browser by defining Shaders with WebGL (JavaScript-based API), so WARP can be easily employed in browser-based exploit development.

The changes were made in a function that is related to WARP Shader JIT code page protection. This particular fix uses new operating system features— VirtualAlloc with the “PAGE_TARGETS_INVALID” flag and the SetProcessValidCallTargets API—to make sure only the starting address of a Shader JIT function is the valid call target. (We will demonstrate this later through a live debugging session.)

20160616 CFG 1

20160616 CFG 2

A look at live debugging before the June Patch (d3d10warp.dll v10.0.10586.0):

20160616 CFG 3

Live debugging after the June Patch (d3d10warp.dll v10.0.10586.420):

20160616 CFG 4

From the preceding screens, we can clearly see that after applying the June patch most bits on the CFG map corresponding to the Shader JIT code block are cleared except for the first (corresponding to the JIT function entry point), which indicates the function entry is the only valid call target and jumping to any other place will be caught by a CFG check.

Looking even deeper into the WARP Shader JIT mechanism, we found some other interesting facts:

  • Unlike with JavaScript/Flash ActionScript JIT, the data and code for the WARP Shader JIT are stored separately (in their dedicated blocks, respectively), which makes it very difficult to control the generation of arbitrary instructions. However, under certain circumstances a specially crafted Shader can still generate a desired ROP gadget that is good enough to bypass CFG. (In most cases the sequence “\x94\xc3” is no longer usable because a CFG check will alter the value in the EAX register.)
  • Some cautious readers may have noticed that all JIT code blocks appear in some continuous and repeated pattern. That is true; WARP Shader JIT does not take randomization into consideration when allocating code pages and generating instructions. As a result, one can generate a desired instruction at some predictable location (as shown in the preceding screen), which is similar to a heap-spray However, to achieve stable WARP Shader JIT spraying, some obstacles need to be overcome. As of now, this issue has not been fixed (and perhaps never will be). I have verified that this flaw can be leveraged in combination with a certain vulnerability to leak the system module’s address.

I plan to write a paper to offer more detail on these aspects. Stay tuned!

I would like to thank my colleague Haifei Li for his help in creating this post.

Categories: McAfee Labs
Tags: , ,

3 comments on “Microsoft’s June Patch Kills Potential CFG Bypass

  • how to trigger the Microsoft Edge load d3d10warp.dll module? I know in the vmware workstation and remote desktop Microsoft Edge load d3d10warp.dll. There are other circumstances ?

    • Basically WARP will come into play when the underlying display hardware doesn’t fully support Direct3D 10, therefore it’s advisable to verify the issue in a virtual machine where the display support is low (such as VMware Fusion, Hyper-v). When running the test PoC inside VMware, if d3dwarp10.dll module is not loaded, please try disabling “Accelerate 3D Graphics” from VM display setting to force it use software based rasterization.
      Interestingly, I tested the issue with the latest MS Hyper-v (both Hyper-v shipped with Windows 8.1 and Windows Hyper-v server 2012), and it turns out that the issue is much easier to reproduce than with VMware. It seems to me that the display device that Hyper-v emulates doesn't fully support D3D 10, such that WARP will be chosen to do the rasterization by default.


Leave a Comment

Similar articles

Let’s Reverse the Threat of Identity Theft!! Our online identities are critical. In fact, you could argue that they are our single most unique asset. Whether we are applying for a job, a mortgage or even starting a new relationship, keeping our online identity protected, secure and authentic is essential. This week is Stay Smart ...
Read Blog
When your baby is on the way, their privacy and digital security is probably the last thing you have on your mind. At least it’s way down there on the list—of course it is! You’re preparing for a bright, joyous addition to your family and home. Everything you’re doing is intended to create an environment ...
Read Blog