BeyondTrust

Security in Context: The BeyondTrust Blog

Welcome to Security in Context

Bringing you news and commentary on solutions and strategies for protecting critical IT infrastructure in the context of your business.

CVE-2014-0301 Analysis

Posted March 19, 2014    BeyondTrust Research Team

This blog post will demonstrate how to leverage binary diffing in order to identify a recently patched Microsoft security flaw leveraging only public data. This is a common practice in the security researcher and attacker space but is a useful reminder for those working in IT how straight forward vulnerability identification can be. For this specific example we will be looking at CVE-2014-0301, which was patched within Microsoft Bulletin MS14-013.

casing the target

Firstly, we gathered as much information about the target vulnerability as possible. By simply looking at the bulletin, it can quickly be seen what files were patched. For Windows 7 (32-bit), the new file information includes qedit.dll, with a file modification date of 2013-06-03.

Next, we made a backup copy of the old versions of the files, installed the update, and made a backup copy of the new versions of the files. At this point we had both a patched and unpatched copy of the qedit.dll file.

finding the patched function

For this example we will be focusing on the Windows 7 version of these files. The first thing to do is to diff the files and see what changed. We did this with DarunGrim3, an automated binary diffing tool. Here are the results of the diff on the patched and unpatched file, sorted by security implication score. (Note: any mis-matched functions have been removed from the listing, so that only functions with matching names between patched and unpatched versions were kept in the list.)

The security implication score assigned by DarunGrim3 is calculated based on several heuristics which are applied to any code added including:

• Addition of a cmp / test instruction.
• Presence of 0xFFFFFFFF anywhere.
• Call to a member of the strlen() family, which generally can be used to patch buffer overflows.
• Call to StringCchCopy() family, which is used to patch buffer overflows.
• Call to ULongLongToULong() which is used to patch integer overflows.

Here are the results of the diff on each file, sorted by security implication score (the mis-matched functions have been removed from the listing):

7 diff functions

A diff of the Windows XP versions of qedit.dll was also performed to help narrow down the patched functions. Here are the patched functions.

xp diff functions

We can see that the functions patched in both Windows XP and Windows 7 are the following:

• LoadJPEGImageNewBuffer
• OpenTGAFile
• OpenDIBFile
• CGenStilVid

Searching for these functions in the popular disassembler, IDA, gives us the following function definitions:

LoadJPEGImageNewBuffer(unsigned short *, class CMediaType *, unsigned char * *)
OpenTGAFile(void *,uchar * *,CMediaType *,uchar *)
OpenDIBFile(void *,uchar * *,CMediaType *,uchar *)
CGenStilVid::~CGenStilVid(void)

~CGenStilVid() diff

The first changed function looks to be a destructor, which might be interesting, but it turns out that there are no real changes, with the exception of changes to file offsets. This makes sense since its implication score was 0. It is safe to rule out this function at this point.

LoadJPEGImageNewBuffer() diff

Most of the changes in this function are caused by what are likely compiler optimizations having to do with comparisons. However, one change is significant. After calling LoadJPEGImage(), the function continues on to a block that deletes a pointer. A new mov[esi], ebx instruction is added. In the patched version of the function, ebx maintains a value of 0, so this new instruction simply clears out the value stored at esi.

At first glance, this is indicative of a patch to a dangling pointer, because the patch is to explicitly clear out a reference to the deleted object, so that it won’t be re-used. In the case of the unpatched CGenStilVid object, it is deleted twice, as we will soon see.

added instruction

OpenTGAFile() diff

A couple registers (eax and ebx) swapped purpose in the last part of this function. This was because the instruction to assign the value at arg_4 to a register was moved further on down in the function. Additionally, at the original place of instantiation, the register is instead set to 0, as can be shown by this diff:

addded instruction

That’s the extent of the meaningful changes in this function.

OpenDIBFile() diff

The changes in this function are similar to OpenTGAFile(). A newly added internal variable is set to zero. Then, some other changes in register/variable usage occurs, but the semantics of the function remain the same.

added instruction

analyzing the changes

It is safe to assume that the changes to OpenTGAFile() and OpenDIBFile() were the result of compiler optimizations, since they did not have any significant bearing on the semantics of either function.

However, the changes to LoadJPEGImageNewBuffer() actually change the purpose of the code, cleaning up what looks like a dangling pointer, so at this point, it is safe to assume that this is the function containing the security patch for CVE-2014-0301.

how to hit the patched function

We tested to see if qedit.dll was loading with common Microsoft programs such as, Excel, Outlook, PowerPoint, Word, Lync, Windows Media Player and even Adobe Acrobat but none of those targets seem to use qedit. So this might only be a vulnerability that more specifically affects 3rd party software using this Microsoft API.

One such 3rd party software, a media player known as Media Player Classic (MPC), will play lots of media types, including JPEG files. When we load up a sample JPEG image in MPC, it will load our target DLL, qedit.dll. The following following JPEG was used for the purposes of this analysis:

test image

When we attach WinDbg to MPC and break on the LoadJPEGImageNewBuffer() function, we can trace execution down to a call to LoadJPEGImage(). If this returns a nonzero result in eax, then our vulnerable code path will be executed.

getting LoadJPEGImage() to fail

There are a few functions called by LoadJPEGImage() that could return error codes. Since invalid size values have been the source of many failures to parse various file formats, our first thought was to mess with the length values in the JPEG image by using a binary file editor, such as 010 Editor. By using the JPG binary template, we simply went through and tested the effects of changing any value that looked like a size value to either 0x00, 0xFF, or 0xFFFF. Most of the values that we changed caused the function to never even get hit. However, we eventually had success in hitting the LoadJPEGImage() function when setting the htInfo value of a Huffmann_Table structure to 0:

htinfo value

With this value set to 0, the image is parsed as usual, but fails during the call to LockBits() with the error stored in eax as 7. Parsing a valid file results with eax being set to 0, which is the Ok Status. According to the MSDN documentation for Bitmap.LockBits(), this error code translates to Win32Error as a part of the Status enumeration.

This error is passed to ResetFormatBuffer(), which is followed directly by ConvertStatustoHR(). The status saved to eax is 0x80004005. At this point, the function cleans up the stack and returns execution back to LoadJPEGImageNewBuffer().

the crash

Once execution is returned back to LoadJPEGImageNewBuffer(), it continues on to a call to delete. This is the first free that occurs.

first free

Later on in the execution, the second free is called on the same object:

second free

The application crashes on the call to ntdll!RtlFreeHeap() during the second call to msvcrt!free().

conclusion

We hope you enjoyed this breakdown of how to diff a patch and produce a crash based off of the diff. Binary diffing is a very useful part of researching vulnerabilities and patches. Obviously there is also the act of successfully producing an exploit for this vulnerability, which can be even more difficult to do than finding the vulnerability itself. We will have to leave that for another write-up!


BeyondTrust Research Team contributions:

• Carter Jones: binary diffing, PoC creation, vulnerability analysis
• Bill Finlayson: sage-like wisdom

Tags:

Leave a Reply

Additional articles

pbps-customer-campaign-image

You Change Your Oil Regularly; Why Not Your Passwords?

Posted September 11, 2014    Chris Burd

There are many things in life that get changed regularly:  your car oil, toothbrush and hopefully, your bed sheets.  It’s rare that you give these things much thought – even when you forget to change them. But what if you’re forgetting something that can cost you millions of dollars if left unchanged for long periods…

Tags:
, , ,

On-Demand Webcast: The Little JPEG that Could (Hack Your Organization) with Marcus Murray

Posted September 10, 2014    Chris Burd

IT security has come a long way, but every once in a while you see something that makes you think otherwise. Every day, internal and external hackers breach and traverse “secure” environments, making you wonder just how easy it is for attackers to completely compromise your network. In a new on-demand BeyondTrust webcast, Marcus Murray,…

Tags:
, , , , ,

Retina Vulnerability Audits – September 2014 Patch Tuesday

Posted September 9, 2014    BeyondTrust Research Team

The following is a list of Retina vulnerability audits for this September 2014 Patch Tuesday: MS14-052 – Cumulative Security Update for Internet Explorer (2977629) 35141 – Microsoft Cumulative Security Update for Internet Explorer (2977629) 35142 – Microsoft Cumulative Security Update for Internet Explorer (2977629) – IE8/2003 35143 – Microsoft Cumulative Security Update for Internet Explorer (2977629) – IE8…