ASLR (Address Space Layout Randomization) is one of the most
effective protection mechanisms in modern operation systems. But it’s
not perfect. Many recent APT attacks have used innovative techniques
to bypass ASLR.
Here are just a few interesting bypass techniques that we have
tracked in the past year:
- Using non-ASLR modules
- Modifying the BSTR length/null terminator
- Modifying the Array object
The following sections explain each of these techniques
Loading a non-ASLR module is the easiest and most popular way to
defeat ASLR protection. Two popular non-ASLR modules are used in IE
zero-day exploits: MSVCR71.DLL and HXDS.DLL.
MSVCR71.DLL, JRE 1.6.x is shipped an old version of the Microsoft
Visual C Runtime Library that was not compiled with the /DYNAMICBASE
option. By default, this DLL is loaded into the IE process at a fixed
location in the following OS and IE combinations:
- Windows 7 and Internet Explorer 8
- Windows 7 and Internet Explorer 9
HXDS.DLL, shipped from MS Office 2010/2007, is not compiled with
ASLR. This technique was first described in here, and is now the
most frequently used ASLR bypass for IE 8/9 on Windows 7. This DLL is
loaded when the browser loads a page with ‘ms-help://’ in the URL.
The non-ASLR module technique requires IE 8 and IE 9 to run with old
software such as JRE 1.6 or Office 2007/2010. Upgrading to the latest
versions of Java/Office can prevent this type of attack.
Modify the BSTR length/null terminator
This technique first appears in the 2010 Pwn2Own
IE 8 exploit by Peter Vreugdenhil. It applies only to specific
types of vulnerabilities that can overwrite memory, such as buffer
overflow, arbitrary memory write, and increasing or decreasing the
content of a memory pointer.
The arbitrary memory write does not directly control EIP. Most of
the time, the exploit overwrites important program data such as
function pointers to execute code. For attackers, the good thing about
these types of vulnerabilities is that they can corrupt the length of
a BSTR so that using the BSTR can access memory outside of its
original boundaries. Such accesses may disclose memory addresses that
can be used to pinpoint libraries suitable for ROP. Once the exploit
has bypassed ASLR in this way, it can then use the same memory
corruption bug to control EIP.
Few vulnerabilities can be used to modify the BSTR length. For
example, some vulnerabilities can only increase/decrease memory
pointers by one or two bytes. In this case, the attacker can modify
the null terminator of a BSTR to concatenate the string with the next
object. Subsequent accesses to the modified BSTR have the concatenated
object’s content as part of BSTR, where attackers can usually find
information related to DLL base addresses.
XFA zero-day exploit uses this technique to find the
AcroForm.api base address and builds a ROP chain dynamically
to bypass ASLR and DEP. With this vulnerability, the exploit can
decrease a controllable memory pointer before calling the function
pointer from its vftable:
Consider the following memory layout before the DEC operation:
After the DEC operation (in my tests, it is decreased twice) the
For further details, refer to the technique write-up from the immunityinc’s blog.
This technique usually requires multiple writes to leak the
necessary info, and the exploit writer has to carefully craft the heap
layout to ensure that the length field is corrupted instead
of other objects in memory. Since IE 9, Microsoft has used Nozzle
to prevent heap spraying/fengshui, so sometimes the attacker must use
technique to craft the heap layout.
Modify the Array object
The array object length modification is similar to the BSTR length
modification: they both require a certain class of “user-friendly”
vulnerabilities. Even batter, from the attacker’s view, is that once
the length changes, the attacker can also arbitrarily read from or
write to memory — or basically take control of the whole process flow
and achieve code execution.
Here is the list of known zero-day exploits using this technique:
This exploit involves Adobe Flash player regex handling
buffer overflow. The attacker overwrites the length of a
Vector.<Number> object, and then reads more memory
content to get base address of flash.ocx.
Here’s how the exploit works:
- Set up a continuous memory layout by allocating the following
- Free the <Number> object at index 1 of the above
objects as follows:
obj = null;
- Allocate the new RegExp object. This allocation reuses
memory in the obj position as follows:
trigger = new RegExp(boom, "");
Later, the malformed expression overwrites the length of a
Vector.<Number> object in
obj to enlarge it. With a corrupted size, the attacker can
use obj to read from or write to memory in a huge region
to locate the flash.ocx base address and overwrite a vftable
to execute the payload.
This vulnerability involves a IE CBlockContainerBlock
object use-after-free error. This exploit is similar to CVE-2013-0634,
but more sophisticated.
Basically, this vulnerability modifies the arbitrary memory content
using an OR instruction. This instruction is something like the following:
or dword ptr [esi+8],20000h
Here’s how it works:
- First, the attacker sprays the target heap memory with
Vector.<uint> objects as follows:.
- After the spray, those objects are stored aligned in a stable
memory address. For example:
The first dword, 0x03f0, is
the length of the Vector.<uint> object, and the
yellow marked values correspond to the values in above spray
- If the attacker sets the esi + 8 point to 0x03f0, the size becomes
0x0203f0 after the OR operation — which is much larger than the
- With the larger access range, the attacker can change the next
object length to 0x3FFFFFF0.
- From there, the attacker can access the whole memory space in the
IE process. ASLR is useless because the attacker can retrieve the
entire DLL images for kernel32/NTDLL directly from memory. By
dynamically searching for stack pivot gadgets in the text section
and locating the ZwProtectVirtualMemory native API address
from the IAT, the attacker can construct a ROP chain to change the
memory attribute and bypass the DEP as follows:
By crafting the memory layout, the attacker also allocates a
Vector.<object> that contains the
flash.Media.Sound() object. The attacker uses the corrupted
Vector.<uint> object to search the sound object in
memory and overwrite it’s vftable to point to ROP payload and shellcode.
The use-after-free vulnerability in Firefox’s
DocumentViewerImpl object allows the user to write a word
value 0x0001 into an arbitrary memory location as follows:
In above code, all the variables that start with “m” are read from
the user-controlled object. If the user can set the object to meet the
condition in the second “if” statement, it forces the code path into
the setImageAnimationMode() call, where the memory write is
triggered. Inside the setImageAnimationMode(), the code looks
like the following:
In this exploit, the attacker tries to use ArrayBuffer to
craft the heap layout. In the following code, each
ArrayBuffer element for var2 has the original size 0xff004.
After triggering the vulnerability, the attacker increases the size
of the array to to 0x010ff004. The attacker can also locate this
ArrayBuffer by comparing the byteLength in
the corrupted ArrayBuffer. In this case, the attacker choose
to disclosure the NTDLL base address from SharedUserData (0x7ffe0300),
and manually hardcoded the offset to construct the ROP payload.
This vulnerability involves a JAVA
CMM integer overflow that allows overwriting the array
length field in memory. During exploitation, the array length
actually expands to 0x7fffffff, and the attacker can search for the
securityManager object in memory and null it to break the
sandbox. This technique is much more effective than overwriting
function pointers and dealing with ASLR/DEP to get native code execution.
The Array object modification technique is much better than
other techniques. For the Flash ActionScript vector technique, there
are no heap spray mitigations at all. As long as you have a
memory-write vulnerability, it is easily implemented.
The following table outlines recent APT zero-day exploits and what
bypass techniques they used:
ASLR bypassing has become more and more common in zero-day attacks.
We have seen previous IE zero-day exploits using Microsoft Office
non-ASLR DLL to bypass it, and Microsoft also did some mitigation in
their latest OS and browser to prevent use of the non-ASLR module to
defeat ASLR. Because the old technique will no longer work and can be
easily detected, cybercriminals will have to use the advanced exploit
technique. But for specific vulnerabilities that allow writing memory,
combining the Vector.<uint> and
Vector.<object> is more reliable and flexible. With
just one shot, extending the exploit from writing a single byte to
reading or writing gigabytes is easy and works for the latest OS and
browser regardless of the OS, application, or language version.
Many researchers have published research on ASLR bypassing, such as
Dion Blazakis’s JIT
spray and Yuyang’s LdrHotPatchRoutine
technique. But so far we haven’t seen any zero-day exploit leveraging
them in the wild. The reason could be that these techniques are
generic approaches to defeating ASLR. And they are usually fixed
quickly after going public.
But there is no generic way to fix vulnerability-specific issues. In
the future, expect more and more zero-day exploits using similar or
more advanced techniques. We may need new mitigations in our OSs and
security products to defeat them.
Thanks again to Dan Caselden and Yichong Lin for their help with