SecureState Blog

Read SecureState's award winning blog.

On December 11, 2012 Microsoft released a Critical Security Bulletin describing avulnerability in the Windows file handling component that could result in remote code execution.  In typical Microsoft fashion, they did not disclose much information about the vulnerability itself.  This vulnerability would be useful for penetration testers and attackers alike depending on how it could be exploited and any other limiting factors.  The following information is the result of a technical analysis of the patch on a Windows XP SP3 system.

 

The patch associated from this vulnerability updates kernel32.dll and primarily changes two functions within it, FindFirstFileExW and FindNextFileW.  What is significant from a reverse engineering perspective is that the logic changes made to these two functions are very similar.  Both functions have an additional check performed on the size parameter that is passed to the memmove function.  Controlling this parameter would be beneficial for an attacker.

 The logic differences surrounding the vulnerable memmove calls

By looking at the code preceding this additional check, logic can be identified that results in the expansion of a string provided to the functions as input.  With this knowledge we can craft a specific file or directory name which can influence the size parameter of the memmove call.  After much trial and error the following Python code was used to craft a suitable directory name.

os.mkdir(‘*.*’ * 56 + ‘\x60\x18DEADBEEF’)

This directory could not be produced on the local NTFS partition, but could however be created on a remote partition, which used the Ext4 filesystem, and is accessed by the victim’s machine via a network share.  The logic prior to the vulnerable memmove call results in the replacement of the asterisk characters with two characters causing the buffer to be expanded.

Due to the expansion of the ‘*.*’ pattern, additional data was written to the buffer resulting in an overflow.  It is important to note that this did not result in an overflow on the stack, but rather on a buffer in the heap.  In the example provided, the characters \x60\x18 overwrite a critical pointer which is referenced after the call toFindNextFileW.  The data that gets overwritten results in control of two bytes of the EDX register in the following assembly stub, setting EDX to 0×00180060.

MOV EAX,DWORD PTR DS:[EDX]

PUSH EDX

CALL DWORD PTR DS:[EAX + 18]

Since both functions convert the file and directory names to Unicode, only two of the four bytes of EDX can directly be influenced.  Furthermore, the options within those two bytes are limited to values below 0×80, as higher values do not seem to be properly converted to Unicode as would be expected.

The assembly stub seems very promising as it allows the attacker to provide a location in memory that will be read for a pointer which will eventually be called.  The problem with exploiting this is the limited control over EDX that the attacker has.  Under ideal conditions the attacker could use a form of heap spraying by creating large amounts of directories with crafted names to allocate data at an address usable by the attacker. In the previous example the address 0×00180060 is used.  The following Python code could produce such a spray.

for x in xrange(0,    200):

os.mkdir(“{0:04}{1}{2}”.format(x, (‘\x41\x41′ * 36), (‘\x30\x18′ * 28)))

With a good deal of luck the second half of the buffer will be located at 0×00180060 with the first half at 0×00180030.  This would result in 0×00410041 being placed at [EAX + 18] and thus called on the third line of the assembly stub.  In the lab environment, this heap spray was successful only one in ten attempts, making this method highly unreliable for a real world attack.  The spray’s effectiveness is also limited by the maximum file and directory name length imposed on the file systems.  The resulting directory structure included the 200 directories creating the spray and an additional directory with an arbitrary name, which contained the directory with the name that would trigger the vulnerability.

At this point the attacker can directly control two of the four bytes of EIP.  There are still restrictions making code execution a difficult goal to obtain.  The restrictions on the directory and file names effectively reduce the space available for shellcode, and the Unicode encoding requires that the shellcode be appropriately encoded, which increases its size.  During execution the attacker can place data within the heap, and this would be the first place that comes to mind when choosing appropriate storage for the shellcode; however Data Execution Protection (DEP) would complicate this storage and require that the shellcode be moved or the permissions on the page modified.  Typically DEP can be defeated by Return-Oriented Programming (ROP) style attacks, which traditionally require control of the stack, something that is not immediately present in this vulnerability but could potentially be obtained through a stack pivot.

Overall, even with ideal conditions there are caveats with obtaining code execution due to the number of constraints.  Between the Unicode encoding, the limited space available in directory and filenames, and the presence of DEP, successfully and reliably exploiting this flaw would be no easy task in a real-world environment.