windows 二进制 -- gdi lib fuzzing

去年这个时间左右,我尝试对windows的gdi库进行fuzz,虽然最终没有获得可以利用的bug,但是我觉得现在分享下代码,回忆下研究经历总是好的。

让我起步的是这篇文章(当然,主要还是蹦着赏金去的)

https://www.4hou.com/posts/jvl5
利用逆向分析与模糊测试技术深入考察Windows图形库漏洞

大体上根据那篇文章写的代码没什么问题,一个小问题就是需要根据这里的指示加一点gdi代码库的初始化。我在这里卡了一段时间,下面是我在stackoverflow上的提问。
https://stackoverflow.com/questions/57847769/emftowmfbits-api-always-returns-0/57848915#57848915

在用cmin缩减了样本后获得了24个emf文件然后进行Fuzz。跑了一阵后,唯一搞出来的有用的那个崩溃最新的win10已经修复了。
最终弄出一个没用的崩溃(一个空指针,报了说不满足他们的漏洞标准)。这之后,我觉得有几条路吧,1是继续尝试下几个别的api,2是结合内核的检测工具试试看。

我后续尝试fuzz了几个其他的emf,wmf相关的api,没有收获。这里的话附上几段代码,感兴趣的朋友可以看下。

整个过程我耗时大概在3,4天吧,在这之后我业余时间就放在web了,不过等后面完成小目标后我肯定会再回来利用业余时间搞二进制的。

EmfToWmfBits

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int fuzzme(char* filename) {
int size = 0;

Metafile myMetafile(charToWChar(filename));
HENHMETAFILE hEmf = myMetafile.GetHENHMETAFILE();

for (size_t indx = 1; indx <= 8; indx++) {
for (size_t indy = 0; indy <= 4; indy++) {
size = Metafile::EmfToWmfBits(
hEmf,
(INT)0,
(INT)NULL,
(INT)indx,
(INT)indy);
}
}


DeleteEnhMetaFile(hEmf);

return 1;
}

SetWinMetaFileBits

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
int fuzzme(char* filename) {

HANDLE hFile = ::CreateFileW(
charToWChar(filename),
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
return NULL;

DWORD dwSize = ::GetFileSize(hFile, NULL);
std::vector<BYTE> data(dwSize);

DWORD dwRead;
BOOL bSuccess = ::ReadFile(hFile, &data[0], dwSize, &dwRead, NULL);
::CloseHandle(hFile);

HENHMETAFILE hEnhMetaFile = NULL;

if (bSuccess)
{
PLACEABLEMETAHEADER* hdr = (PLACEABLEMETAHEADER*)& data[0];
int iPlaceableHeaderSize = sizeof(PLACEABLEMETAHEADER);

int iOffset = 0;
if (hdr->key != 0x9AC6CDD7) //not placeable header
{
iOffset = 0; //offset remains zero
}
else
{
iOffset = iPlaceableHeaderSize; //file is offset with placeable windows metafile header
}

hEnhMetaFile = ::SetWinMetaFileBits(data.size(), &data[iOffset], NULL, NULL);
if (NULL == hEnhMetaFile)
{
DWORD dwError = GetLastError();
std::cout << "Failed with error code: " << dwError;
}
else
{
std::cout << "Success! Metafile opened and returned as enhanced metafile";
}
}

return 1;
}

ConvertToEmfPlus

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
int fuzzme(char* filename) {
HWND hWnd;
PAINTSTRUCT ps;

HINSTANCE hInstance = GetModuleHandle(0);
hWnd = CreateWindow(szAppName, // window class name
szAppName, // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
400, // initial x size
300, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL);

HDC hdc = BeginPaint(hWnd, &ps);
HDC hDC = GetDC(hWnd);

Graphics graphics(hdc);
Metafile myMetafile(charToWChar(filename));
INT conversionSuccess;

for (int i = 1; i <= 3; i++) {
if (i == 1) {
Gdiplus::Status status = myMetafile.ConvertToEmfPlus(&graphics, &conversionSuccess, Gdiplus::EmfTypeEmfPlusDual, NULL);
}
else if (i == 2) {
Gdiplus::Status status = myMetafile.ConvertToEmfPlus(&graphics, &conversionSuccess, Gdiplus::EmfTypeEmfOnly, NULL);
}
else {
Gdiplus::Status status = myMetafile.ConvertToEmfPlus(&graphics, &conversionSuccess, Gdiplus::EmfTypeEmfPlusOnly, NULL);
}
}

ShowWindow(hWnd, 3);

ReleaseDC(hWnd, hDC);
EndPaint(hWnd, &ps);
GdiFlush();

return 1;
}

PlayEnhMetaFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
int fuzzme(char* filename) {
int size = 0;
HWND hWnd;
PAINTSTRUCT ps;
WNDCLASS wndclass;
RECT rect;


Metafile myMetafile(charToWChar(filename));
HENHMETAFILE hEmf = myMetafile.GetHENHMETAFILE();

for (size_t indx = 1; indx <= 8; indx++) {
for (size_t indy = 0; indy <= 4; indy++) {
size = Metafile::EmfToWmfBits(
hEmf,
(INT)0,
(INT)NULL,
(INT)indx,
(INT)indy);
}
}


HINSTANCE hInstance = GetModuleHandle(0);
hWnd = CreateWindow(szAppName, // window class name
szAppName, // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
400, // initial x size
300, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL);

HDC hdc = BeginPaint(hWnd, &ps);

rect.left = 0;
rect.top = 0;
rect.right = 20;
rect.bottom = 20;

HDC hDC = GetDC(hWnd);
GetClientRect(hWnd, &rect);
PlayEnhMetaFile(hDC, hEmf, &rect);

DeleteEnhMetaFile(hEmf);

ReleaseDC(hWnd, hDC);
EndPaint(hWnd, &ps);

GdiFlush();
return 1;
}

代码就这些了,不确定一年过去了这些代码能不能fuzz出崩溃来,如果你搞到了洞,记得请我喝杯咖啡。 :)