Another 0day, Another Prevention
The bulk of the worker thread is designed to drive the exploitation in the following steps.
- Prepare memory by allocating a large number of objects to address 0x30000030.
- Trigger the usage of the free memory in the original exploit function which will corrupt the allocated heap blocks.
- Use the memory class to leak the base address of XUL.dll.
- Use the PE class to resolve the import address of Kernel32.dll!CreateThread.
- Dynamically construct the ROP chain using the ROP class.
- Store the addresses of the ROP chain and payload in memory.
- Trigger the control flow hijack that calls the stack pivot to initiate the ROP chain.
While this vulnerability was surely discovered while fuzzing, the exploit writer wasn’t a novice. The use of the helper functions to dynamically build the payload is of moderate skill.
After analyzing the exploit we quickly wanted to determine how our Endgame exploit prevention techniques would do against this never-before-seen vulnerability and exploit.
Endgame has two distinct approaches to exploit prevention. One uses our novel Hardware-Assisted Control-Flow-Integrity (HA-CFI) that can predict when a branch misprediction is about to execute malicious instructions. The other consists of dynamically inserted checks that are performed during program execution.
When testing HA-CFI against exploits, we really want to catch the exploit before that ROP chain. This gives the defender an earlier place to determine whether something “bad” is about to happen. In this instance, because we know this UAF will eventually alter control flow, we were able to successfully detect that first change. Using IDA, we have visualized the detection information straight from HA-CFI's alert. The source is the exact location of the control-flow hijack, and the destination is the beginning of the ROP chain. It is important to note that we block the destination address from ever executing.
Pretty neat! As an added bonus it helps us when reverse engineering exploits because we know exactly where the bug is.
As mentioned earlier, we also have a dynamic ability to detect exploits as well. We call this DBI, for Dynamic Binary Instrumentation. When talking about exploit prevention, there is early and late stage detection. Late detection is typical of most exploit prevention software. For an experienced exploit writer, the later a detection the easier it is to bypass. This is why it is essential to detect exploits as early as possible with innovative techniques such as HA-CFI and new DBI checks.
Our recently released DBI prevention check has proven to detect early against this vulnerability. The new protection is designed to detect when an attacker is attempting to dynamically resolve PE imports, and construct a ROP chain. By doing this we actually catch the exploit in Step 4 above. Below is some output from a debug version of the software showing exactly what happened.
You can see that the exploit tried to read the header of xul.dll (base address 0x695c0000). And if we disassemble the source of the read we see an executable JIT page making the offending read.
Stay tuned for the next release, where some of our latest research is designed to catch exploits even earlier, in Stage 1.
At this point, 0days should not surprise anyone. They have been, and will be, a regular occurrence. However, in this case targeting Firefox and Tor is particularly unique, as Tor is often used for illegal purposes, and exploiting the user's browser is a quick way to “de-anonymize” the user. Also, unlike most exploit kits, this exploit doesn’t appear to be highly obfuscated, which also differentiates it from other 0days.