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.
/* now load the element, recursively */
error = Load_SBit_Image( strike,
x_offset + comp->x_offset,
y_offset + comp->y_offset,
depth + 1 );
This new offset value (y_offset + comp->y_offset) will be used to compute the memory pointer (line_buff).
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.
.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 🙂