January 14, 2014

Flash Player Unloading Vulnerability III

This is the third article in this series that I didn't expect to write but it turns out the fix for CVE-2013-5332 insufficiently addresses the issue around the dialog boxes. Adobe had issued a fix that prevents the testcase I provided them from crashing the plugin but it's still possible to reach the bug just by adding an additional step to that testcase. I talked to Adobe about this.

Now the crash state is different to the crash state previously seen but in both cases the instruction dereferences freed memory. The vulnerability enables the attacker to divert the execution flow via the dispatch table that can be constructed due to a use-after-free issue.

I'm using Application Verifier and GFlags tool to make the vulnerability easy to see, and I'm also doing this because I observed that the application didn't crash at certain times. It could have happened because an object was allocated to the freed memory in a way to contain a valid function pointer. So rather than dereferencing freed memory the wrong function was called by the dispatcher and the execution completed without access violation.

Anyway here is the configuration. I configured GFlags for Internet Explorer 11 like below.

Configured Application Verifier, too.

In Windbg, I set debug of child process so when to open iexplore.exe from the disk I'm able to debug both broker and renderer processes. In the beginning of the article I mentioned that an additional step is required to the testcase in order to trigger the bug. It is to visit a web page that contains a Flash object which simply is to exercise the Flash plugin. After that, we can load the testcase to trigger the dialog box seen below.

At this point we can see many problems reported by Application Verifier. Here are two.
=======================================
VERIFIER STOP 00000202: pid 0xBE0: Freeing heap block containing an active critical section.

4C3D6FE0 : Critical section address.
00DEF2FC : Critical section initialization stack trace.
4C3D6FE0 : Heap block address.
0000001C : Heap block size.

=======================================
[...]
=======================================
VERIFIER STOP 00000350: pid 0xBE0: Unloading DLL that allocated TLS index that was not freed.

004BABBA : TLS index
6759965F : Address of the code that allocated this TLS index.
4B916FCE : DLL name address. Use du to dump it.
67060000 : DLL base address.

=======================================
After the close of dialog box the instruction at 6724f02b dereferences freed memory during processing the dispatch table. I highlighted the vulnerable path that can execute injected code.
(c44.e64): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\system32\Macromed\Flash\Flash32_11_9_900_170.ocx -
eax=0b611060 ebx=0b5fd0a0 ecx=7ffd7000 edx=6e1027a4 esi=0b5ef000 edi=0b612020
eip=6724f02b esp=067fc018 ebp=067fc028 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
Flash32_11_9_900_170!DllUnregisterServer+0x173da:
6724f02b 8b7024 mov esi,dword ptr [eax+24h] ds:0023:0b611084=????????
2:055> u
Flash32_11_9_900_170!DllUnregisterServer+0x173da:
6724f02b 8b7024 mov esi,dword ptr [eax+24h] <--Read freed memory
6724f02e eb02 jmp Flash32_11_9_900_170!DllUnregisterServer+0x173e1 (6724f032)
6724f030 33f6 xor esi,esi
6724f032 85f6 test esi,esi
6724f034 7420 je Flash32_11_9_900_170!DllUnregisterServer+0x17405 (6724f056)

6724f036 8b06 mov eax,dword ptr [esi] <--Read attacker controlled memory
6724f038 8bce mov ecx,esi
6724f03a ff5004 call dword ptr [eax+4] <--Divert execution
 I recorded a video of the vulnerability using the latest Flash Player (12.0.0.38) for Internet Explorer.

January 10, 2014

Triaging crash on instruction "call [rax]"

The following Python script causing handled access violation when it's executed with Python 2.7.6.
import tkMessageBox
import time

time.sleep(6)
The exception can be caught by the following command.
C:\Work>"c:\Program Files\Debugging Tools for Windows (x64)\windbg.exe" -g c:\Python27\python.exe messagebox.py
Then Windbg displays:
(c2a4.c374): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for c:\Python27\DLLs\tk85.dll -
tk85!Tk_MainLoop+0x122:
00000000`102de8b2 ff9068030000    call    qword ptr [rax+368h] ds:00000000`00000368=????????????????
call [rax] suggests to pay attention because the issue could be exploitable if rax is attacker controlled.

We can see the crash happens when we read address near null so you may think it's a non-exploitable null pointer dereference. However to confirm this we need to investigate how rax is set to null. If null is read from previously freed memory we may have the chance to corrupt the memory in a way to inject arbitrary pointer therefore to make the issue exploitable.

So the preceding instruction sets rax that is:
0:000> ub rip L1
tk85!Tk_MainLoop+0x11b:
00000000`102de8ab 488b0576bd0d00  mov     rax,qword ptr [tk85!XDrawLine+0x59b98 (00000000`103ba628)]
We can see the address is fixed, relative to tk85, which was allocated when the module was being loaded in the virtual address space. Now we can say with more confidence the issue is a non-exploitable null pointer dereference.

Python 3.x doesn't support tkMessageBox so it's not affected.

January 9, 2014

Using Pintools to Detect Bugs II: Overlap of Regions

There are functions that can take source and destination parameters to copy data. That functions include the followings: strncpy(), strncat(), memcpy(), wcsncpy(), wcsncat(), strcat(), strcpy(), wcscat(), wcscpy(), CopyMemory(), sscanf(), printf(), swscanf(), swprintf(). If the destination and source regions overlap the behavior is undefined. This really means one of the regions can get partly overwritten when copying. I wrote about this earlier.

Some time ago I wrote a tool to detect such errors runtime and I used Pin framework. Though I've never seen an exploitable bug regarding this classification it's still valuable to detect these issues as the attacker could write memory that he's not supposed to. This could lead to enter the program in an inconsistent state.

The tool I wrote produces the following straightforward output on the test sample.
Overlap of source and destination regions at 6c79396f in wcsncat(021b1ee8,021b1eec,8)
  Stack
    001efd90 7c 10 eb 00 e8 1e 1b 02 ec 1e 1b 02 08 00 00 00
    001efda0 74 33 eb 00 01 00 00 00 07 12 eb 00 01 00 00 00
    001efdb0 58 3e 1b 02 40 5c 1b 02 10 5a cc 31 00 00 00 00
    001efdc0 00 00 00 00 00 e0 fd 7e 00 00 00 00 00 00 00 00
  Source
    021b1eec 75 00 72 00 63 00 65 00 20 00 73 00 74 00 72 00
    021b1efc 69 00 6e 00 67 00 00 00 00 00 00 00 00 00 00 00
    021b1f0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    021b1f1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  Destination
    021b1ee8 73 00 6f 00 75 00 72 00 63 00 65 00 20 00 73 00
    021b1ef8 74 00 72 00 69 00 6e 00 67 00 00 00 00 00 00 00
    021b1f08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    021b1f18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
You may ask what's the news to detect this bug as Valgrind can do for ages. Well, my approach is not to use symbols, source code, or any debug information so I can apply my tests against arbitrary binaries.

Even just few string copy functions were added to the tool I had found plenty low-severity bugs in high-profile applications by this approach.

Here is the tool. Feel free to improve it according to your needs.

UPDATE 15/January/2014 Added CopyMemory() to the list.
UPDATE 2/February/2014 Added sscanf(), printf(), swscanf(), swprintf() to the list. Reference.
  This blog is written and maintained by Attila Suszter. Read in Feed Reader.