GDI Font Fuzzing in Windows Kernel for Fun Kernel for Fun
Lee Ling Chuan & Chan Lee Yee
Ministry of Science, Technology and Innovation
GDI Font Fuzzing in Windows Kernel for Fun Kernel for Fun Lee Ling - - PowerPoint PPT Presentation
GDI Font Fuzzing in Windows Kernel for Fun Kernel for Fun Lee Ling Chuan & Chan Lee Yee Ministry of Science, Technology and Innovation Agenda Agenda Introduction TrueType Font (.TTF) TTF Fuzzer Exploit Demonstration MS11
Lee Ling Chuan & Chan Lee Yee
Ministry of Science, Technology and Innovation
Microsoft Windows Bitmapped font (.fon)
modification modification
3/16/2012 2
three types: yp
Reference: http://msdn microsoft com/en us/library/dd162893(v=vs 85) aspx Reference: http://msdn.microsoft.com/en‐us/library/dd162893(v=vs.85).aspx
3/16/2012 3
Raster fonts: a glyph is a bitmap that uses to draw a single character in the font
endpoints that define the line segments and uses to draw a character in the font uses to draw a character in the font
ll i f li d d ll collection of line and curve commands as well as a collection of hints
3/16/2012 4
TrueType font file contains data, in table format, that compromises an outline font
The outlines of glyphs in TrueType fonts are made of straight line segments and quadratic Bézier curves
using the hints inside the TTF file.
correct oversights
3/16/2012 5
TTF table is designed to keep the entire glyph data in various table: a EBDT: Embedded Bitmap Data Table
EBSC E b dd d Bit S li T bl
diff t t d th l h d t i th f t differents to render the glyph data in the font
R f T T 1 0 F Fil T h i l S ifi i R i i 1 66 A 1995 Mi f Reference: TrueType 1.0 Font File, Technical Specification Revision 1.66 August 1995 Microsoft
3/16/2012 6
TrueType embedded bitmaps are also called ‘scaler bitmaps’ or ‘sbits’
called a strike
3/16/2012 7
TTF Font Structure
3/16/2012 8
.TTF Font Structure
EBDT Embedded Bitmap Data Table:
b h ‘ ’ bl b i i h h d
containing simply the table version number
bitmap data bitmap data
3/16/2012 9
EBDT Table Structure
3/16/2012 10
EBDT Table Structure
range of the sbits, and keeps offsets to glyph bit d t i i d S bT bl bitmap data in indexSubTables
(eblcHeader) containing the table version and (eblcHeader) containing the table version and number of strikes.
bitmapSizeTable array(s)
3/16/2012 11
3/16/2012 12
EBLC Table Structure
p g
bitmap strike as a scaled version of another strike
containing the table version and number of strikes
bitmapScaleTable array. The numSizes in the b H d i di t th b f ebscHeader indicates the number of bitmapScaleTables in the array d Each strike is defined by one bitmapScaleTable
3/16/2012 13
3/16/2012 14
EBSC Table Structure
a This table contains information that
describes the glyphs in the font
tasks: ‐ Pushing data onto the interpreter stack managing the Storage Area ‐ managing the Storage Area ‐ managing the Control Value Table ‐ modifying Graphics State settings y g p g ‐ Managing outlines ‐ General purpose instructions
3/16/2012 15
th i d their opcodes. GLYFDirectoryEntry ‐> DataGLYFData[x+1]‐> SimpleGLYFData[x]‐> instructions
– function[0xB0]: itrp_PUSHB1 p_ – function[0xB8]: itrp_PUSHW1
3/16/2012 16
f ti [0 1C] it JMPR ‐ function[0x1C]: itrp_JMPR ‐ function[0x1F]: itrp_LSW ‐ function[0x78]: itrp JROT function[0x78]: itrp_JROT
‐ function[0x20]: itrp_DUP ‐ function[0x23]: itrp_SWAP
function[0x43]: itrp RS ‐ function[0x43]: itrp_RS ‐ function[0x42]: itrp_WS
3/16/2012 17
‐ function[0x44]: itrp_WCVT ‐ function[0x45]: itrp_RCVT
‐ function[0x4D]: itrp_FLIPON ‐ function[0x4E]: itrp_FLIPOFF
‐ function[0x60]: itrp_ADD ‐ function[0x61]: itrp SUB function[0x61]: itrp_SUB
Reference: Chapter Appendix B, TrueType 1.0 Font File, Technical Specification Revision 1.66 August 1995 Microsoft
3/16/2012 18
Important info (1) in exploitation:
structure fnt_GlobalGraphicStateType{ stackBase; /*the stack area stackBase; / the stack area store; /*the storage area controlValueTable; /*the control value table …… int8 non90DegreeTransformation /*bit0: 1 if non‐90 degree /*bit 1:1 if x scale not equal y scale …… unit16 cvtCount; } fnt_GlobalGraphicStateType;
3/16/2012 19
p ( ) p ‐ function ‘itrp_InnerExecute’ as the disassembler engine to process Glyph Data and map to correct TrueType instructions TrueType instructions
+0 : stackBase +0 : stackBase +4: store +8: controlValueTable +8: controlValueTable +90h: non90DegreeTransformation +134h: cvtCount
3/16/2012 20
3/16/2012 21
The TrueType Instruction Set
itrp_InnerExecute
3/16/2012 22
Glyph data in hexadicimal format
itrp_InnerExecute
3/16/2012 23
Glyph data in hexadicimal format
itrp_InnerExecute
;Function[0xB0]: itrp_PUSHB1 ;’00’ is parameter of the instruction
3/16/2012 24
Glyph data in hexadicimal format
itrp_PUSHB1
;ecx: parameter ‘00’ ;esi: pointer structure fnt_GlobalGraphicStateType+0
3/16/2012 25
Glyph data in hexadicimal format
different sizes
font handle (HFONT) W k ith f t t l l l th h f t
APIs: GetFontData, GetGlyphIndices, ExtTextOut with ETO_GLYPH_INDEX flag _ _ g
Reference: http://blogs.msdn.com/b/text/archive/2009/04/15/introducing‐the‐ directwrite‐font‐system.aspx
3/16/2012 26
a automating the installation of the crafted
font in ‘C:\WINDOWS\Fonts’ folder
h dll d dd (f l ) htr=windll.gdi32.AddFontResourceExA(fileFont, FR_PRIVATE, None)
window to automate the display of the font window to automate the display of the font text in a range of font size c Remove the fonts in ‘C:\WINDOWS\Fonts’
folder
windll.gdi32.RemoveFontResourceExW(fileFont, FR PRIVATE, None) windll.gdi32.RemoveFontResourceExW(fileFont, FR_PRIVATE, None)
3/16/2012 27
lf=win32gui.LOGFONT() for fontsize in range (0, 100, 1): lf.lfHeight=fontsize lf.lfFaceName="Dexter" lf lf d h lf.lfWidth=0 lf.lfEscapement=0 lf.lfOrientation=0 lf lfWeight=FW NORMAL lf.lfWeight=FW_NORMAL lf.lfItalic=False lf.lfUnderline=False lf lfStrikeOut=False lf.lfStrikeOut False lf.lfCharSet=DEFAULT_CHARSET lf.lfOutPrecision=OUT_DEFAULT_PRECIS lf.lfClipPrecision=CLIP_DEFAULT_PRECIS f f p _ _ lf.lfPitchAndFamily=DEFAULT_PITCH|FF_DONTCARE
3/16/2012 28
font text font text
windll.gdi32.ExtTextOutW( windll.gdi32.ExtTextOutW( hdc, 5, 5, ETO_GLYPH_INDEX, None, var1 var1, len(var1), None)
3/16/2012 29
3/16/2012 30
3/16/2012 31
Name Value Description EBSC.bitmapScaleTable[0].ppemX 0x004 Target horizontal pixels per Em EBSC.bitmapScaleTable[0].ppemY 0x004 Target vertical pixels per Em EBLC.bitmapSizeTable[5].ppemX 0x001 Horizontal pixels per Em EBLC bit Si T bl [5] Y 0 001 V ti l i l E EBLC.bitmapSizeTable[5].ppemY 0x001 Vertical pixels per Em EBDT.bitmapData.EbdtFormat8[11]. smallMetrics.height 0x001 Number of rows of data EBDT.bitmapData.EbdtFormat8[11]. smallMetrics.width 0x0ff Number of columns of data EBDT.bitmapData.EbdtFormat8[11]. 0x040 Position of component left ebdtComponent[0].xOffset EBDT.bitmapData.EbdtFormat8[11]. ebdtComponent[0].yOffset 0x052 Position of component top
Important info in exploitation
3/16/2012 32
=(EBLC.ppemX+((EBSC.ppemX*2)* EBDT.width))/(2*EBLC.ppemX) EBDT.width))/(2 EBLC.ppemX) =(0x001+((0x004*2)*0x0ff))/(2*0x001) (0 001 0 7F8)/(0 002) = (0x001+0x7F8)/(0x002) = 0x03FC
3/16/2012 33
usScaleHeight = (EBLC.ppemY+((EBSC.ppemY*2)*EBDT.height)) /(2*EBLC ppemY) /(2 EBLC.ppemY) =(0x001+0x008)/(0x002) 0 0004 = 0x0004
3/16/2012 34
usScaleRowBytes =((usScaledWidth+0x1F)>>3)&(0xFFFC) ((0 03 C 0 ) 3)& (0 C) = ((0x03FC+0x1F)>>3)& (0xFFFC) = (0x85)&(0xFFFC) = 0x80
3/16/2012 35
usOriginalRowBytes = ((EBDT.width+0x1F)>>3)&(0xFFFC) ((0 0 ) 3)&(0 C) = ((0x0FF+0x1F)>>3)&(0xFFFC) = 0x20
3/16/2012 36
Byte of scaling bitmap data =usScaleHeight*usScaleRowBytes = 0x004*0x080 = 0x004 0x080 = 0x200 R i d b t f li bit d t ff t
= (EBDT.yOffset)*(usOriginalRowBytes) = 0x52*0x20 = 0x0A40
3/16/2012 37
structure fnt_GlobalGraphicStateType{ stackBase; /*the stack area store; /*the storage area store; / the storage area controlValueTable; /*the control value table …… int8 non90DegreeTransformation …… unit16 cvtCount; } fnt_GlobalGraphicStateType;
BEFORE AFTER
3/16/2012 38
structure fnt_GlobalGraphicStateType{ stackBase; /*the stack area store; /*the storage area store; / the storage area controlValueTable; /*the control value table …… int8 non90DegreeTransformation …… unit16 cvtCount; } fnt_GlobalGraphicStateType;
BEFORE AFTER
3/16/2012 39
fnt_GlobalGraphicStateType+134h (cvtCount) BEFORE AFTER
3/16/2012 40
3/16/2012 41
3/16/2012 42
ecx: value ‘stackBase+0’ edx: value Control Value Table
3/16/2012 43
3/16/2012 44
3/16/2012 45
Perfectly jump into Perfectly jump into the shellcode
3/16/2012 46
3/16/2012 47
Microsoft Windows Bitmapped Fonts (.fon) come in two different types:
Windows 3)NE
executable format used in Windows 95 and above)
Note: Can’t find any complete documentation of Microsoft Windows Bitmapped Font. If you have any, share with me ☺!!
3/16/2012 48
k f
‐ written and/or maintained by Simon Tatham ‐ python script generates NE fon files only python script generates NE .fon files only
i b ‐ written by Byoungyoung Lee ‐ fuzz the .fon in different width, height
3/16/2012 49
k i f
value = string.atol(w, 16) ;support hexadecimal
if width != 0: if width ! 0: for j in range(height): fdStr += "A"*width + "\n“ fd "\ " fdStr += "\n"
3/16/2012 50
3/16/2012 51
Discovered by Byoungyoung Lee
i b b b d h l i Interesting bug but based on the analysis, there is very difficult to bypass the ‘safe li ki ’ i i d k l l unlinking’ in windows kernel pool
Possible to bypass the Stack‐Canary in Kernel Land Land
3/16/2012 52
win32k!BmfdOpenFontContext
;.Fon width=498 (0x1F2)
3/16/2012 53
; eax=(0x1F2)*5=0x9ba
win32k!BmfdOpenFontContext ;the ‘EngAllocMem’ function allocates a block of memory (0x160) and inserts
3/16/2012 54
;a ‘Bmfd’ pool tag before the allocation
3/16/2012 55
;Font data ‘aa’ will process and the result as index to read from the following array:
jS h5B1
3/16/2012 56
3/16/2012 57
Overwrite 3 bytes in l h d next pool header
3/16/2012 58
win32k!vStretchGlyphBitmap
3/16/2012 59
win32k!vStretchGlyphBitmap
win32k!vStretchGlyphBitmap
3/16/2012 60
win32k!vStretchGlyphBitmap
3/16/2012 61
3/16/2012 62
Possible to bypass Kernel Canary in Kernel Land??
3/16/2012 63
Possible to bypass Kernel Canary in Kernel Land?? gave up without detail testing
3/16/2012 64
3/16/2012 65