Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=951 Platform: GDI on Windows 7 x86 reachable from Microsoft Office 2010 Class: Out of bounds memory access The following crash was observed in Microsoft Office 2010 running under Windows 7 x86 with Application Verifier enabled. Attached files: 2167705722.ppt: fuzzed crashing file File versions: gdi32.dll: 6.1.7601.23457 gdiplus.dll: 6.1.7601.23508 gfx.dll: 14.0.7104.5000 oart.dll: 14.0.7169.5000 (788.ca0): Access violation - code c0000005 (first chance) eax=00000000 ebx=0747bc5c ecx=00000001 edx=16ab9fd8 esi=1c45dcb8 edi=223e3000 eip=77667a68 esp=1c45dc78 ebp=1c45dc84 iopl=0 nv up ei pl nz ac pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010216 GDI32!ConvertDxArray+0x3c: 77667a68 8b07 mov eax,dword ptr [edi] ds:0023:223e3000=???????? 0:014> kb ChildEBP RetAddr Args to Child 1c45dc84 7765a2b3 000003a8 0747bc5c 223e2ff0 GDI32!ConvertDxArray+0x3c 1c45e6dc 776442e7 1f210a94 0000001b 00000093 GDI32!MF_ExtTextOut+0x3b4 1c45ec48 776405dc 1f210a94 0000001b 00000093 GDI32!ExtTextOutInternalA+0x156 1c45ec74 7764969c 1f210a94 0000001b 00000093 GDI32!ExtTextOutA+0x24 1c45ed5c 7764e40f 1f210a94 0ab42fc8 0747bc42 GDI32!PlayMetaFileRecord+0x1bc7 1c45ede0 7764e441 21464dc0 0000000c 00000000 GDI32!CommonEnumMetaFile+0x24d 1c45edf8 741fb1c0 1f210a94 2a260a92 7764438a GDI32!PlayMetaFile+0x1f 1c45ee60 741fb65b 2a260a92 43b405d9 46123597 GdiPlus!GetEmfFromWmfData+0x420 1c45ee84 741fb768 2a260a92 1c45eec8 00000000 GdiPlus!GpMetafile::InitWmf+0xb2 1c45eea0 741fea9f 2a260a92 1c45eec8 00000000 GdiPlus!GpMetafile::GpMetafile+0x3b 1c45eef8 741ff642 19a0cd28 1c45efbc 00000000 GdiPlus!GpMetafile::ConvertToEmfPlus+0x79 1c45ef1c 741d4fc2 19a0cd28 1c45efbc 00000004 GdiPlus!GpMetafile::ConvertToEmfPlus+0x1d 1c45ef58 6b388b58 19a0cd28 1999ef28 1c45efbc GdiPlus!GdipConvertToEmfPlus+0xbf 1c45efd4 6b36f2f4 19a0cd28 00000000 1fd76f56 gfx!Ordinal841+0x12250 1c45f004 678980c2 1c45f07c 1c45f024 1fd75519 gfx!Ordinal745+0x34 1c45f090 67897d68 1c45f0e8 07430f28 21408fe0 oart!Ordinal7931+0x6d0 1c45f104 677e340d 07430f28 1c45f124 67805b69 oart!Ordinal7931+0x376 1c45f110 67805b69 1c45f2c8 1c45f1b0 6b24cceb oart!Ordinal3235+0x14a The function GDI32!ConvertDxArray is called with codepage 936 (ANSI/OEM Simplified Chinese [PRC, Singapore]; Chinese Simplified [GB2312]) a length of 4 (DWORDs) and a source contents containing 0x00000010 0x00000000 0x00000010 0x00000000. There are two paths in this function, one that operates on 4 byte boundaries and one that operates on 8 byte boundaries depending on the last argument where true indicates an 8-byte boundary and false indicates a 4-byte boundary. Both paths have the same issue. Pseudocode for one path in the function is: ... else if ( (unsigned int)current < result ) { cur_dest = (unsigned int *)dest; cur_src = (unsigned int *)src; do { dbcs_ret = IsDBCSLeadByteEx(CodePage, *current++); dbcs_flag = dbcs_ret == 0; tmp = *cur_src; *cur_dest = tmp; if ( !dbcs_flag ) { ++cur_src; tmp = *cur_src; // crash here ++current; *cur_dest += tmp; } ++cur_src; ++cur_dest; } while ( (unsigned int)current < end ); } The issue here is that when dbcs_flag is false the 4 byte boundary version can actually process 8 bytes of the source buffer (cur_src is incremented twice) and the 8 byte version is capable of processing 16 bytes per iteration. The length checks in this function do not verify this behavior to be in bounds. However, the most likely exploitation scenario will be a memory disclosure because cur_dest is not written to out of bounds. The value in tmp is instead added to the contents of cur_dest. Proof of Concept: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41419.zip # Iranian Exploit DataBase = http://IeDb.Ir [2017-02-22]