MS06-001 Windows Metafile Escape() SetAbortProc Code Execution 漏洞分析
SoBeIt
WindowsMetaFile文件格式用于储存图片,与位图文件最大的不同在于它的设备无关性,无论向什么设备输出,它总能保持里面图片的原始尺寸和象素。它们主要用于Windows 3.x,保存到现在主要是为了兼容性。它的内部文件结构是由一个文件头WMFHEAD结构和若干个WMFRECORD结构组成。它们的结构定义如下:
typedef struct _WindowsMetaHeader
{
WORD FileType; /* Type of metafile (0=memory, 1=disk) */
WORD HeaderSize; /* Size of header in WORDS (always 9) */
WORD Version; /* Version of Microsoft Windows used */
DWORD FileSize; /* Total size of the metafile in WORDs */
WORD NumOfObjects; /* Number of objects in the file */
DWORD MaxRecordSize; /* The size of largest record in WORDs */
WORD NumOfParams; /* Not Used (always 0) */
} WMFHEAD;
typedef struct _StandardMetaRecord
{
DWORD Size; /* Total size of the record in WORDs */
WORD Function; /* Function number (defined in WINDOWS.H) */
WORD Parameters[]; /* Parameter values passed to function */
} WMFRECORD;
然后每个wmf文件以一个特定的6个字节标记\x03\x00\x00\x00\x00\x00结尾。在构造metafile时,用于显示该图象的所有GDI函数和它们的参数按调用顺序存储进每个WMFRECORD结构里。整个wmf文件长度必须按2字节对齐,若不足可以在结尾标记前补齐。
发生漏洞时函数顺序如下:
..GDI32!PlayMetaFile
....GDI32!CommonEnumMetaFile
......GDI32!PlayMetaFileRecord
........GDI32!Escape
..........GDI32!SetAbortProc
Escape的函数索引在wingdi.h里定义:
#define META_ESCAPE 0x0626
ESCAPE函数声明如下:
int Escape(
HDC hdc, // handle to device context
int nEscape, // escape function
int cbInput, // number of bytes in input structure
LPCSTR lpvInData, // pointer to input structure
LPVOID lpvOutData // pointer to output structure
);
当这样构造WMFRECORD结构时: