Monthly Archives: January 2012

MS11-087 (aka Duqu) : Vulnerability in Windows kernel-mode drivers could allow remote code execution

Update (Feb 2, 2012) :
Since many folks are asking more about MS11-087, I’m posting some of interesting questions I’ve got.

Q. How to parse TTF sbit ?
Microsoft FontTools have ‘SBIT32’ and ‘TTFDUMP’, each of which can be useful to understand sbit. I’ve also written simple TTF sbit parser, which supports EBLC and EBDT table. . This python script would be much better to see how it works.

Q. Is it working on Windows 64 bit ?
A. I’m not sure. Vulnerability itself would be still effective on Win64. However, since DEP on Win64 also protects dynamically allocated memory, it may not work without doing Return Oriented Programming. If you are clever enough, you might be able to write a memory map parser using TTF interpreter to find the gadget address for ROP.

Q. Why .ttf is not triggering MS11-087 ?
A. sbit routine is kicked in only if the point resolution is matched. Default fontviewer (default .ttf handler on windows) may not trigger MS11-087. You need to embed .ttf into word documents or html documents, and setup the proper resolution for that document. Word document allows to set the viewing resolution into the document. This may implicate very reliable kernel exploit through IE was possible.

Update (Jan 30, 2012) : After some thoughts, I have decided not to disclose any more details of MS11-087 (yeah. ethical issue). Last comments for duqu is… this is an amazing exploit. On 32bit Windows, ASLR and DEP are just useless on duqu. My guess is the author of duqu may have the access to the windows kernel source code. They have understood very deep details of the data structure used by win32k.sys font engine. Yes, they played with TTF fonts just like a toy. I am kind of sad that I cannot share this amazing exploit with many other security folks.

Related CVE : CVE-2011-3402

Before Patch : win32k.sys 6.1.7601.17697 (win7sp1_gdr.110928-1505)
After Patch : win32k.sys 6.1.7601.17730 (win7sp1_gdr.111123-1510)

Duqu was extremely critical. Office documents and even Internet Explorer could be used as attack vectors, and also it is kernel exploit ! Moreover, the attack could be quite reliable though it is kernel exploit 🙂 A font engine inside the kernel is indeed a bad design decision ?

Many different sources have covered duqu’s malicious behaviors before, but I believe this post would be the first to cover *vulnerability* itself. Unlike previous exploitshop post, this post will focus on how duqu attack is working instead of focusing how win32k.sys is patched.

MS11-087 analysis was quite complicated because
1) ttf itself is already complicated. Sbit is even worse (Most ttf open source implementations are supporting sbit incompletely).
2) MS11-087 patch itself is not obvious. MS touched many different parts of ttf font engines, including multiple integer overflow patches (I’m not quite sure this is actually a positive bug). I wasted lots of my time to see these integer overflow issues, and… yeah MS seems to know how to confuse a patch analysis 🙂

1) Preliminary stage: one-byte overwrite
When ttf bitmap is loaded to the memory, no boundary check was done. This allows to overwrite multiple bytes to certain ranges of heap address with user controlled value. Successful exploitation requires only one-byte overwrite though. This one-byte overwrite enables easy read&write operations to TTF interpreter context data structure later.

To be specific, each glyph in EBDT table (See MS EBDT specification) is loaded one by one to the allocated memory. (Imagine how type-writer is working. A character (Each glyph) is typed onto the paper, and the next character will be typed next to the previous character.) To properly position the glyphs, each glyph has the layout information including height, width, x_offset, and y_offset. One glyph is loaded first, and then the next glyph will be loaded while moving the position a little.

For better understanding, let’s see freetype2 implementation. Load_SBit_Image() of freetype2 is corresponding to GetSbitComponent() of win32k. When it makes the recursive call to handle the glyphs one by one, you can see component type x_offset and y_offset are added to the ones before.


ttsbit.c::Load_SBit_Image()::line 1387
/* now load the element, recursively */
error = Load_SBit_Image( strike,
elem_range,
ebdt_pos,
elem_offset,
slot,
x_offset + comp->x_offset,
y_offset + comp->y_offset,
stream,
&elem_metrics,
depth + 1 );

This new offset value (y_offset + comp->y_offset) will be used to compute the memory pointer (line_buff).


ttsbit.c::blit_sbit()::line 105
line_buff += ( x_offset >> 3 ) + y_offset * line_incr;

Then let’s how this is working in win32k (before patch). The analogy from freetype2 would be really helpful to understand. Yeah… it is working pretty much the same for this process.


win32k!sfac_GetSbitBitmap()
...
.text:BF8EEDFF imul ecx, eax ; ecx -> y_offset * line_incr
...
.text:BF8EEE75 mov eax, [ebp+a16] ; eax -> x_offset >> 3
.text:BF8EEE78 lea esi, [ecx+eax] ;
...
.text:BF8EEE85 mov al, [ebx] ; al -> image value
.text:BF8EEE87 or [esi], al ; esi -> line_buff

line_buff can be manipulated as follows. Having win32k load a component glyph first, which has big y_offset value. This will setup the target bitmap memory. Next, having win32k load a glyph with image data. This will write image data using (possibly) big line_buff pointer value caused by big y_offset value. This actually allows multiple-bytes overwrite with controlled data to a certain range of heap address. Duqu overwrote 1-byte to manipulate CVT table size.

MS11-087 patched this problem by adding the boundary check routines. There’s many other patches, but this would be the specific one for Duqu.


.text:BF8EEF64 cmp eax, [ebp+pBufMax]
.text:BF8EEF67 ja loc_BF8EF160
.text:BF8EEF6D cmp eax, [ebp+pBufBase]
.text:BF8EEF70 jb loc_BF8EF160
.text:BF8EEF76 mov dl, [ebx]
.text:BF8EEF78 or [eax], dl

2) Exploit stage
will be posted very soon. Exploit is also very interesting. Duqu tamed the TrueType Interpreter 🙂

Advertisements

MS12-005 : embedded object package allow arbitrary code execution

MS12-005 is really fun.
See our video capture – http://t.co/g4BKbgGF

Updates 2 : MS12-005 is much more dangerous than I thought. Very easy to exploit, and 100% reliable. Now no user interactions are required. Exploit is available : http://www.cc.gatech.edu/~blee303/exploit/ms12-005/MS12-005.ppsx . Download this and double-click the ppsx file (PPT presentation file) would execute the python scripts 🙂 In this ppsx, customized animations were used to activate the embedded document (python script), which would be activated as the document opened. No permission checks are required. Thanks to Yorick.

Updates 1 : See http://seclists.org/fulldisclosure/2012/Jan/164 for the attack vector. This guy seems to be the founder of MS12-005, and it suggests to use office and .application. You may want to check if this also requires the user interaction (like enabling the macro).

Before patch : packager.dll, 6.1.7600.16385 (win7_rtm.090713-1255)
After patch : packager.dll, 6.1.7601.17727 (win7sp1_gdr.111118-2330)

Here’s some background for MS12-005 (see http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/packager_what_is_obj_pkg.mspx?mfr=true). Object packager can embed any files into the other file, and this is also true for office documents. You can simply drag-and-drop any files into the office document, then the icon of that file will be shown in the document. By double-clicking the icon, you can execute the embedded file if it is executable. Surely packager.dll pops up the warning message which says “DONT DO THIS, IT IS DANGEROUS”, and it requires the confirmation from the user.

The problem of MS12-005 lies in 1) how to identify the executable file and 2) how to show the warning message to the user.

1. How to identify the executable file
Before the patch, packager.dll identifies the executable by matching them with the table (let’s say execExtTable).

.text:02FA1D98 execExtTable dd offset a_exe ; DATA XREF: CPackage::_GetCurrentIcon(_IC *)+69o
.text:02FA1D98 ; CPackage::_GiveWarningMsg(HWND__ *)+5Eo
.text:02FA1D98 ; “.exe”
.text:02FA1D9C dd offset a_com ; “.com”
.text:02FA1DA0 dd offset a_bat ; “.bat”
.text:02FA1DA4 dd offset a_lnk ; “.lnk”
.text:02FA1DA8 dd offset a_cmd ; “.cmd”
.text:02FA1DAC dd offset a_pif ; “.pif”
.text:02FA1DB0 dd offset a_scr ; “.scr”
.text:02FA1DB4 dd offset a_js ; “.js”
.text:02FA1DB8 dd offset a_jse ; “.jse”
.text:02FA1DBC dd offset a_vbs ; “.vbs”
.text:02FA1DC0 dd offset a_vbe ; “.vbe”
.text:02FA1DC4 dd offset a_wsh ; “.wsh”
.text:02FA1DC8 dd offset a_sct ; “.sct”
.text:02FA1DCC dd offset a_vb ; “.vb”
.text:02FA1DD0 dd offset a_wsc ; “.wsc”
.text:02FA1DD4 dd offset a_wsf ; “.wsf”
.text:02FA1DD8 dd offset a_wmz ; “.wmz”

Just looping through that table to see if the embedded file has the same extension name.
This is actually done by calling the function IsProgIDInList.

.text:02FA72F4 push 11h ; int
.text:02FA72F6 push offset execExtTable ; dangerousTable
.text:02FA72FB push esi ; pExtName
.text:02FA72FC push 0 ; int
.text:02FA72FE call ?IsProgIDInList@@YGHPBG0PBQBGI@Z ; IsProgIDInList(ushort const *,ushort const *,ushort const * const *,uint)

WHAT?? Only these extensions are executables? There are a lot more executable extension as you may know. Though it could be system specific depending on the execution handlers are installed (yeah.. this reminds me of old windows vulnerability), .py and .pl should be popular enough. In this point, I am sure some other folks might be able to come up with better attack vectors (.vsto could be the one ??).

MS12-005 patched this issue by calling AssocIsDangerous() to check the executable extension.

.text:02FA6A11 push eax
.text:02FA6A12 call ds:__imp__AssocIsDangerous@4 ; AssocIsDangerous(x)
.text:02FA6A18 test eax, eax
.text:02FA6A1A jnz short loc_2FA6A42

Try this using DarunGrim. It specifically shows up that this block has been changed 🙂

2) how to show the warning message
This is simple part. Before the patch, packager.dll shows up the warning message only if it is executable. See the function : CPackage___GiveWarningMsg(HWND hWnd). This function loops over execExtTable again, and IT WON’T SHOW THE WARNING MESSAGES if it is not in execExtTable !!!

How to Exploit.
Our video capture on youtube shows everything (http://t.co/g4BKbgGF). To be simple, we used python scripts to embed into office documents, and wrote the macro to execute (double-click) this embedded python script. After opening the office document, you need to confirm to execute the macro and it will execute python scripts right away.