Author:dge
通过阅读微软安全公告和CVE-2008-2245,我们可以知道这是个发生在MSCMS模块里的堆溢出,CVE甚至给出了漏洞函数InternalOpenColorProfile。这个漏洞也是跟EMF图片有关,POC地址在这里:http://milw0rm.com/sploits/2008-emf_MS08-046.rar。
本来可以直接对InternalOpenColorProfile函数进行分析,并且对其进行设断的,不过我在IDA里没找到这个函数,用PAIMEI定位到溢出点后才知道,IDA识别出了这个符号,只不过没把它放到FUNCTIONS列表里面,我们可以在NAMES列表里找到它,不过没关系,用PAIMEI找它也很简单。
说下跟踪步骤:
先用PAIMEI跟踪,在跟踪记录中从后望前找,既然是堆溢出,那肯定得有堆分配的函数,而且在其附近代码中很可能有指向输入数据的寄存器和拷贝函数,这样很容易可以定位到溢出点,下一步就是在OD中对发生溢出的函数设断,中断后查看调用栈就可以获得漏洞触发路径了,如果这样不行的话,那就只能继续向上翻看PAIMEI的跟踪记录了,因为它记录的内容超多,所以有点麻烦,当然也可以只对函数进行跟踪,不过IDA在识别函数上经常出现问题,所以PAIMEI也会跟着倒霉。
漏洞产生路径:
PlayEnhMetaFileRecord
|_MRSETICMPROFILE::bPlay
|_SetICMProfileInternalA
|_IcmSetDestinationColorSpace
|_IcmCreateColorSpaceByName
|_IcmCreateColorSpaceByColorSpace
|_IcmRealizeColorProfile
|_OpenColorProfileW
|_lstrcatW
POC截图:
蓝框就是RECORD的内容,当程序把它拷贝到小的堆中导致了溢出。
下边就仔细分析下这个漏洞:
.text:77EFEF66 __stdcall PlayEnhMetaFileRecord(x, x, x, x) proc near
.text:77EFEF66 ; CODE XREF: bInternalPlayEMF(x,x,x,x,x)+6A2 p
.text:77EFEF66 ; bInternalPlayEMF(x,x,x,x,x)+13B2 p ...
.text:77EFEF66
.text:77EFEF66 var_58 = dword ptr -58h
.text:77EFEF66 var_54 = dword ptr -54h
.text:77EFEF66 var_50 = dword ptr -50h
.text:77EFEF66 var_4C = dword ptr -4Ch
.text:77EFEF66 var_48 = dword ptr -48h
.text:77EFEF66 var_44 = dword ptr -44h
.text:77EFEF66 var_40 = dword ptr -40h
.text:77EFEF66 var_3C = dword ptr -3Ch
.text:77EFEF66 var_38 = dword ptr -38h
.text:77EFEF66 var_34 = dword ptr -34h
.text:77EFEF66 var_30 = dword ptr -30h
.text:77EFEF66 var_2C = dword ptr -2Ch
.text:77EFEF66 var_28 = dword ptr -28h
.text:77EFEF66 var_24 = dword ptr -24h
.text:77EFEF66 var_20 = dword ptr -20h
.text:77EFEF66 var_1C = dword ptr -1Ch
.text:77EFEF66 var_18 = dword ptr -18h
.text:77EFEF66 var_14 = dword ptr -14h
.text:77EFEF66 var_10 = dword ptr -10h
.text:77EFEF66 var_C = dword ptr -0Ch
.text:77EFEF66 var_8 = dword ptr -8
.text:77EFEF66 var_4 = dword ptr -4
.text:77EFEF66 arg_0 = dword ptr 8
.text:77EFEF66 arg_4 = dword ptr 0Ch
.text:77EFEF66 arg_8 = dword ptr 10h
.text:77EFEF66 arg_C = dword ptr 14h
.text:77EFEF66
.text:77EFEF66 ; FUNCTION CHUNK AT .text:77F18A61 SIZE 0000028A BYTES
.text:77EFEF66
.text:77EFEF66 mov edi, edi
.text:77EFEF68 push ebp
.text:77EFEF69 mov ebp, esp
.text:77EFEF6B sub esp, 58h
.text:77EFEF6E push ebx
.text:77EFEF6F mov ebx, [ebp+arg_8]
.text:77EFEF72 mov eax, [ebx]
.text:77EFEF74 cmp eax, 1
.text:77EFEF77 push esi
.text:77EFEF78 push edi
.text:77EFEF79 jb short loc_77EFEF99
.text:77EFEF7B cmp eax, 7Ah
.text:77EFEF7E ja short loc_77EFEF99
.text:77EFEF80 push [ebp+arg_C]
.text:77EFEF83 mov ecx, ebx
.text:77EFEF85 push [ebp+arg_4]
.text:77EFEF88 push [ebp+arg_0]
.text:77EFEF8B call _fpStartDocDlgW[eax*4] ; eax必须是70
.text:77EFEF92
.text:77EFEF92 loc_77EFEF92: ; CODE XREF: PlayEnhMetaFileRecord(x,x,x,x)+19D72 j
.text:77EFEF92 ; PlayEnhMetaFileRecord(x,x,x,x)+19D80 j
.text:77EFEF92 pop edi
.text:77EFEF93 pop esi
.text:77EFEF94 pop ebx
.text:77EFEF95 leave
.text:77EFEF96 retn 10h
.text:77EFEF99 ; ---------------------------------------------------------------------------
上图中的红线上边必须是0x70,这样才可以让数据流到达MRSETICMPROFILE::bPlay。
.text:77F2EA1B public: int __thiscall MRSETICMPROFILE::bPlay(void *, struct tagHANDLETABLE *, unsigned int) proc near
.text:77F2EA1B ; DATA XREF: .data:77F3279C o
.text:77F2EA1B ; .data:77F327A0 o
.text:77F2EA1B
.text:77F2EA1B var_46C = dword ptr -46Ch
.text:77F2EA1B var_468 = dword ptr -468h
.text:77F2EA1B var_464 = dword ptr -464h
.text:77F2EA1B var_460 = dword ptr -460h
.text:77F2EA1B var_45C = dword ptr -45Ch
.text:77F2EA1B var_458 = dword ptr -458h
.text:77F2EA1B var_454 = dword ptr -454h
.text:77F2EA1B var_450 = dword ptr -450h
.text:77F2EA1B var_44C = dword ptr -44Ch
.text:77F2EA1B var_448 = dword ptr -448h
.text:77F2EA1B var_414 = dword ptr -414h
.text:77F2EA1B var_20C = byte ptr -20Ch
.text:77F2EA1B var_4 = dword ptr -4
.text:77F2EA1B arg_0 = dword ptr 8
.text:77F2EA1B arg_4 = dword ptr 0Ch
.text:77F2EA1B
.text:77F2EA1B mov edi, edi
.text:77F2EA1D push ebp
.text:77F2EA1E mov ebp, esp
.text:77F2EA20 sub esp, 46Ch
.text:77F2EA26 mov eax, ___security_cookie
.text:77F2EA2B push esi
.text:77F2EA2C mov [ebp+var_4], eax
.text:77F2EA2F mov eax, [ebp+arg_4]
.text:77F2EA32 push edi
.text:77F2EA33 mov edi, [ebp+arg_0]
.text:77F2EA36 push eax
.text:77F2EA37 mov esi, ecx
.text:77F2EA39 mov [ebp+var_460], edi
.text:77F2EA3F call MRNAMEDESCAPE::bCheckRecord(tagHANDLETABLE *) ; 这里必须符合[esi+10h]+[esi+c]&0FFFFFFFCh==[esi+4h]
.text:77F2EA44 test eax, eax
.text:77F2EA46 jz loc_77F2EBA2
.text:77F2EA4C push ebx
.text:77F2EA4D xor ebx, ebx
.text:77F2EA4F test byte ptr [esi+8], 1 ; [esi+8h]必须等于0
.text:77F2EA53 mov [ebp+var_45C], ebx
.text:77F2EA59 jz loc_77F2EB74
当esi指向上图蓝色的位置时,[esi+10h]+[esi+c]&0FFFFFFFCh==[esi+4h],[esi+8h]必须等于0。
.text:77F2EB74 loc_77F2EB74: ; CODE XREF: MRSETICMPROFILE::bPlay(void *,tagHANDLETABLE *,uint)+3E j
.text:77F2EB74 cmp dword ptr [esi], 70h
.text:77F2EB77 push 10002h ; int
.text:77F2EB7C push ebx ; int
.text:77F2EB7D jnz short loc_77F2EB8B
.text:77F2EB7F add esi, 14h
.text:77F2EB82 push esi ; lpString
.text:77F2EB83 push edi ; HDC
.text:77F2EB84 call SetICMProfileInternalA(x,x,x,x)
.text:77F2EB89 jmp short loc_77F2EB95
.text:77F2EB8B ; ---------------------------------------------------------------------------
.text:77F20F7F __stdcall SetICMProfileInternalA(x, x, x, x) proc near
.text:77F20F7F ; CODE XREF: SetICMProfileA(x,x)+F p
.text:77F20F7F ; MRSETICMPROFILE::bPlay(void *,tagHANDLETABLE *,uint)+169 p
.text:77F20F7F
.text:77F20F7F var_210 = dword ptr -210h
.text:77F20F7F u_string = byte ptr -20Ch
.text:77F20F7F var_4 = dword ptr -4
.text:77F20F7F hdc = dword ptr 8
.text:77F20F7F lpString = dword ptr 0Ch
.text:77F20F7F const_0 = dword ptr 10h
.text:77F20F7F const_10002 = dword ptr 14h
.text:77F20F7F
.text:77F20F7F mov edi, edi
.text:77F20F81 push ebp
.text:77F20F82 mov ebp, esp
.text:77F20F84 sub esp, 210h
.text:77F20F8A mov eax, ___security_cookie
.text:77F20F8F and [ebp+var_210], 0
.text:77F20F96 push ebx
.text:77F20F97 mov ebx, [ebp+const_0]
.text:77F20F9A test ebx, ebx
.text:77F20F9C push esi
.text:77F20F9D mov esi, [ebp+hdc]
.text:77F20FA0 push edi
.text:77F20FA1 mov edi, [ebp+lpString]
.text:77F20FA4 mov [ebp+var_4], eax
.text:77F20FA7 jnz short loc_77F20FB1
.text:77F20FA9 test edi, edi
.text:77F20FAB jz loc_77F2104E
……
.text:77F21004 test edi, edi
.text:77F21006 jz short loc_77F21046
.text:77F21008 push edi ; lpString
.text:77F21009 call ds:lstrlenA(x)
.text:77F2100F test eax, eax
.text:77F21011 jz short loc_77F2103F
.text:77F21013 cmp eax, 104h ; 如果RECORD的长度大于等于0x104就失败,所以最长是103字节
.text:77F21018 jnb short loc_77F2103F
.text:77F2101A inc eax ; 加上\0,最大长度为104字节
.text:77F2101B push eax
.text:77F2101C push edi
.text:77F2101D push 0
.text:77F2101F push 208h
.text:77F21024 lea eax, [ebp+u_string]
.text:77F2102A push eax
.text:77F2102B call ds:RtlMultiByteToUnicodeN(x,x,x,x,x) ; 把字符串转换成Unicode编码格式
.text:77F21031 push [ebp+const_10002]
.text:77F21034 lea eax, [ebp+u_string]
.text:77F2103A push 0
.text:77F2103C push eax
.text:77F2103D jmp short loc_77F20FF2
……
.text:77F20FF2 loc_77F20FF2: ; CODE XREF: SetICMProfileInternalA(x,x,x,x)+BE j
.text:77F20FF2 push esi ; hdc
.text:77F20FF3 call IcmSetDestinationColorSpace(x,x,x,x)
.text:77F20FF8 ; ---------------------------------------------------------------------------
由上边的分析可知字符串最大长度为0x103字节。
.text:77F20CD3 __stdcall IcmSetDestinationColorSpace(x, x, x, x) proc near
.text:77F20CD3 ; CODE XREF: SetICMProfileInternalA(x,x,x,x)+74 p
.text:77F20CD3 ; SetICMProfileInternalW(x,x,x,x)+56 p ...
.text:77F20CD3
.text:77F20CD3 var_4 = dword ptr -4
.text:77F20CD3 hdc = dword ptr 8
.text:77F20CD3 lpString2 = dword ptr 0Ch
.text:77F20CD3 const_0 = dword ptr 10h
.text:77F20CD3 const_10002 = dword ptr 14h
.text:77F20CD3
.text:77F20CD3 mov edi, edi
.text:77F20CD5 push ebp
.text:77F20CD6 mov ebp, esp
.text:77F20CD8 push ecx
.text:77F20CD9 push ebx
.text:77F20CDA push esi
.text:77F20CDB xor esi, esi
.text:77F20CDD cmp [ebp+const_0], esi
.text:77F20CE0 push edi
.text:77F20CE1 jnz short loc_77F20D08
.text:77F20CE3 cmp [ebp+lpString2], esi
.text:77F20CE6 jz loc_77F20F71
.text:77F20CEC push [ebp+lpString2] ; lpString
.text:77F20CEF call ds:lstrlenW(x)
.text:77F20CF5 cmp eax, esi
.text:77F20CF7 jz loc_77F20F71
.text:77F20CFD cmp eax, 104h
.text:77F20D02 ja loc_77F20F71
…….
.text:77F20D97 loc_77F20D97: ; CODE XREF: IcmSetDestinationColorSpace(x,x,x,x)+B5 j
.text:77F20D97 cmp [ebp+const_0], 0
.text:77F20D9B jnz short loc_77F20DC4
.text:77F20D9D push [ebp+const_10002] ; int
.text:77F20DA0 push dword ptr [esi+30h] ; int
.text:77F20DA3 push [ebp+lpString2] ; wchar_t *
.text:77F20DA6 push ebx ; int
.text:77F20DA7 call IcmGetColorSpaceByName(x,x,x,x)
.text:77F20DAC test eax, eax
.text:77F20DAE mov [ebp+const_0], eax
.text:77F20DB1 jnz short loc_77F20DEE
.text:77F20DB3 push [ebp+const_10002] ; int
.text:77F20DB6 push dword ptr [esi+30h] ; int
.text:77F20DB9 push [ebp+lpString2] ; lpString2
.text:77F20DBC push ebx ; hdc
.text:77F20DBD call IcmCreateColorSpaceByName(x,x,x,x)
.text:77F20DC2 jmp short loc_77F20DE3
.text:77F20DC4 ; ---------------------------------------------------------------------------
.text:77F0335B __stdcall IcmCreateColorSpaceByName(x, x, x, x) proc near
.text:77F0335B ; CODE XREF: IcmUpdateLocalDCColorSpace(x,x)+1043 p
.text:77F0335B ; IcmUpdateLocalDCColorSpace(x,x)+150B7 p ...
.text:77F0335B
.text:77F0335B struct_ = byte ptr -250h
.text:77F0335B var_4 = dword ptr -4
.text:77F0335B hdc = dword ptr 8
.text:77F0335B lpString2 = dword ptr 0Ch
.text:77F0335B arg_8 = dword ptr 10h
.text:77F0335B const_10002 = dword ptr 14h
.text:77F0335B
.text:77F0335B mov edi, edi
.text:77F0335D push ebp
.text:77F0335E mov ebp, esp
.text:77F03360 sub esp, 250h
.text:77F03366 mov eax, ___security_cookie
.text:77F0336B mov edx, [ebp+lpString2]
.text:77F0336E push esi
.text:77F0336F mov esi, [ebp+hdc]
.text:77F03372 mov [ebp+var_4], eax
.text:77F03375 push edi
.text:77F03376 xor eax, eax
.text:77F03378 mov ecx, 93h
.text:77F0337D lea edi, [ebp+struct_]
.text:77F03383 rep stosd
.text:77F03385 and dword ptr [ebp+struct_+0Ch], eax
.text:77F0338B mov eax, [ebp+arg_8]
.text:77F0338E mov dword ptr [ebp+struct_+10h], eax
.text:77F03394 push edx ; lpString2
.text:77F03395 lea eax, [ebp+struct_+44h]
.text:77F0339B push eax ; lpString1
.text:77F0339C mov dword ptr [ebp+struct_], 50534F43h ;装填结构变量
.text:77F033A6 mov dword ptr [ebp+struct_+4], 400h
.text:77F033B0 mov dword ptr [ebp+struct_+8], 24Ch
.text:77F033BA call ds:lstrcpyW(x,x) ; 把字符串拷贝到struct_+0x44
.text:77F033C0 push [ebp+const_10002]
.text:77F033C3 lea eax, [ebp+struct_]
.text:77F033C9 push 0
.text:77F033CB push eax ; 结构指针
.text:77F033CC push esi ; hdc
.text:77F033CD call IcmCreateColorSpaceByColorSpace(x,x,x,x)
.text:77F033D2 mov ecx, [ebp+var_4]
.text:77F033D5 pop edi
.text:77F033D6 pop esi
.text:77F033D7 call __security_check_cookie(x)
.text:77F033DC leave
.text:77F033DD retn 10h
.text:77F033DD __stdcall IcmCreateColorSpaceByName(x, x, x, x) endp
.text:77F033DD
.text:77F033DD ; ---------------------------------------------------------------------------
构造一个结构体变量做为参数传入,在这个结构体0x44偏移处包含RECORD的字符串。
.text:77F033E5 __stdcall IcmCreateColorSpaceByColorSpace(x, x, x, x) proc near
.text:77F033E5 ; CODE XREF: IcmCreateColorSpaceByName(x,x,x,x)+72 p
.text:77F033E5 ; IcmCreateColorTransform(x,x,x,x)+DDD p ...
.text:77F033E5
.text:77F033E5 hdc = dword ptr 8
.text:77F033E5 lp_struct = dword ptr 0Ch
.text:77F033E5 const_0 = dword ptr 10h
.text:77F033E5 const_10002 = dword ptr 14h
.text:77F033E5
.text:77F033E5 ; FUNCTION CHUNK AT .text:77F037FC SIZE 00000039 BYTES
.text:77F033E5 ; FUNCTION CHUNK AT .text:77F1684C SIZE 00000126 BYTES
.text:77F033E5
.text:77F033E5 mov edi, edi
.text:77F033E7 push ebp
.text:77F033E8 mov ebp, esp
.text:77F033EA push ebx
.text:77F033EB push esi
.text:77F033EC mov esi, [ebp+lp_struct]
.text:77F033EF xor ebx, ebx
.text:77F033F1 test esi, esi
.text:77F033F3 push edi
.text:77F033F4 jz loc_77F03529
.text:77F033FA cmp _ghICM, ebx
.text:77F03400 jz loc_77F1684C
……
.text:77F03493 ; IcmCreateColorSpaceByColorSpace(x,x,x,x)+134B7 j ...
.text:77F03493 mov eax, [ebp+lp_struct]
.text:77F03496 cmp [eax+44h], cx ; 检查RECORD的第一个字节内容是否为0
.text:77F0349A jz loc_77F1690E
.text:77F034A0 push edi ; size_t
.text:77F034A1 lea esi, [ebx+70h]
.text:77F034A4 push esi ; int
.text:77F034A5 push esi ; wchar_t *
.text:77F034A6 call BuildIcmProfilePath(x,x,x)
.text:77F034AB push offset aSrgbColorSpace ; "sRGB Color Space Profile.icm"
.text:77F034B0 push eax ; wchar_t *
.text:77F034B1 call ds:__imp___wcsicmp
.text:77F034B7 test eax, eax
.text:77F034B9 pop ecx
.text:77F034BA pop ecx
.text:77F034BB jnz short loc_77F034C1
.text:77F034BD or dword ptr [ebx+0Ch], 1
.text:77F034C1
.text:77F034C1 loc_77F034C1: ; CODE XREF: IcmCreateColorSpaceByColorSpace(x,x,x,x)+D6 j
.text:77F034C1 mov dword ptr [ebx+20h], 1
.text:77F034C8 mov [ebx+24h], esi
.text:77F034CB mov dword ptr [ebx+28h], 208h
.text:77F034D2
.text:77F034D2 loc_77F034D2: ; CODE XREF: IcmCreateColorSpaceByColorSpace(x,x,x,x)+13514 j
.text:77F034D2 ; IcmCreateColorSpaceByColorSpace(x,x,x,x)+13524 j ...
.text:77F034D2 push 0
.text:77F034D4 push ebx ; ebx指向新的堆
.text:77F034D5 call IcmRealizeColorProfile(x,x)
.text:77F034DA ; ---------------------------------------------------------------------------
程序新建了个堆,并把前边构造的结构体变量复制到其中。
.text:77F032DD __stdcall IcmRealizeColorProfile(x, x) proc near
.text:77F032DD ; CODE XREF: IcmCreateColorSpaceByColorSpace(x,x,x,x)+F0 p
.text:77F032DD ; IcmCreateColorTransform(x,x,x,x)+E4D p ...
.text:77F032DD
.text:77F032DD lp_st = dword ptr 8
.text:77F032DD const_0 = dword ptr 0Ch
.text:77F032DD
.text:77F032DD ; FUNCTION CHUNK AT .text:77F037E0 SIZE 0000001C BYTES
.text:77F032DD ; FUNCTION CHUNK AT .text:77F162CE SIZE 0000000C BYTES
.text:77F032DD
.text:77F032DD mov edi, edi
.text:77F032DF push ebp
.text:77F032E0 mov ebp, esp
.text:77F032E2 push esi
.text:77F032E3 mov esi, [ebp+lp_st]
.text:77F032E6 test esi, esi
.text:77F032E8 jz loc_77F037F4
.text:77F032EE cmp dword ptr [esi+14h], 0
.text:77F032F2 jnz short loc_77F0331F
.text:77F032F4 cmp dword ptr [esi+24h], 0
.text:77F032F8 jz short loc_77F0331F
.text:77F032FA push edi
.text:77F032FB push 3
.text:77F032FD push 3
.text:77F032FF push 1
.text:77F03301 lea eax, [esi+20h]
.text:77F03304 push eax
.text:77F03305 call _fpOpenColorProfileW ; 这里调用mscms模块里的OpenColorProfileW函数
.text:77F0330B mov edi, eax
.text:77F0330D test edi, edi
.text:77F0330F jz short loc_77F0331E
.text:77F03311 cmp [ebp+const_0], 0
.text:77F03315 jnz loc_77F037E0
.text:77F0331B
.text:77F0331B loc_77F0331B: ; CODE XREF: IcmRealizeColorProfile(x,x)+50C j
.text:77F0331B mov [esi+14h], edi
.text:77F0331E
.text:77F0331E loc_77F0331E: ; CODE XREF: IcmRealizeColorProfile(x,x)+32 j
.text:77F0331E ; IcmRealizeColorProfile(x,x)+12FF8 j
.text:77F0331E pop edi
.text:77F0331F
.text:77F0331F loc_77F0331F: ; CODE XREF: IcmRealizeColorProfile(x,x)+15 j
.text:77F0331F ; IcmRealizeColorProfile(x,x)+1B j
.text:77F0331F xor eax, eax
.text:77F03321 cmp [esi+14h], eax
.text:77F03324 setnz al
.text:77F03327
.text:77F03327 loc_77F03327: ; CODE XREF: IcmRealizeColorProfile(x,x)+51A j
.text:77F03327 pop esi
.text:77F03328 pop ebp
.text:77F03329 retn 8
.text:77F03329 __stdcall IcmRealizeColorProfile(x, x) endp
上边调用MSCMS模块里的函数OpenColorProfileW。
.text:73AA1D96 __stdcall OpenColorProfileW(x, x, x, x) proc near
.text:73AA1D96 ; CODE XREF: DoesProfileMatchEnumRecord(x,x)+49 p
.text:73AA1D96 ; GetProfileClassString(x,x,x)+58 p
.text:73AA1D96
.text:73AA1D96 SecurityAttributes= _SECURITY_ATTRIBUTES ptr -18h
.text:73AA1D96 var_C = dword ptr -0Ch
.text:73AA1D96 var_8 = dword ptr -8
.text:73AA1D96 var_4 = dword ptr -4
.text:73AA1D96 lpString1 = dword ptr 8
.text:73AA1D96 const_1 = dword ptr 0Ch
.text:73AA1D96 dwShareMode = dword ptr 10h
.text:73AA1D96 dwCreationDisposition= dword ptr 14h
.text:73AA1D96
.text:73AA1D96 ; FUNCTION CHUNK AT .text:73AA2559 SIZE 00000051 BYTES
.text:73AA1D96 ; FUNCTION CHUNK AT .text:73AA3A77 SIZE 00000163 BYTES
.text:73AA1D96
.text:73AA1D96 mov edi, edi
.text:73AA1D98 push ebp
.text:73AA1D99 mov ebp, esp
.text:73AA1D9B pop ebp
.text:73AA1D9C nop
.text:73AA1D9D nop
.text:73AA1D9E nop
.text:73AA1D9F nop
.text:73AA1DA0 nop
.text:73AA1DA1
.text:73AA1DA1 __stdcall InternalOpenColorProfile(x, x, x, x):
.text:73AA1DA1 ; CODE XREF: OpenColorProfileA(x,x,x,x)+70 p
.text:73AA1DA1 mov edi, edi
.text:73AA1DA3 push ebp
.text:73AA1DA4 mov ebp, esp
.text:73AA1DA6 sub esp, 18h
.text:73AA1DA9 push ebx
.text:73AA1DAA push esi
.text:73AA1DAB mov esi, [ebp+lpString1]
.text:73AA1DAE xor ebx, ebx
.text:73AA1DB0 cmp esi, ebx
.text:73AA1DB2 push edi
.text:73AA1DB3 mov [ebp+var_8], ebx
.text:73AA1DB6 jz loc_73AA2577
.text:73AA1DBC mov edi, ds:IsBadReadPtr(x,x)
……
.text:73AA1E67 mov eax, [edi+4] ; 指向输入串
.text:73AA1E6A test eax, eax
.text:73AA1E6C jz loc_73AA2563
.text:73AA1E72 cmp dword ptr [edi+8], 0
.text:73AA1E76 jz loc_73AA2563
.text:73AA1E7C push eax ; lpString
.text:73AA1E7D call ds:lstrlenW(x)
.text:73AA1E83 mov esi, 104h
.text:73AA1E88 cmp eax, esi
.text:73AA1E8A jg loc_73AA2563 ; 串长度必须小于等于208字节
.text:73AA1E90 cmp dword ptr [edi+8], 208h
.text:73AA1E97 ja loc_73AA2563
.text:73AA1E9D push dword ptr [ebx+0Ch] ; lpszStart
.text:73AA1EA0 call GetFilenameFromPath(x)
.text:73AA1EA5 cmp eax, [ebx+0Ch]
.text:73AA1EA8 jz loc_73AA3AA2
…….
.text:73AA3AA2 loc_73AA3AA2: ; CODE XREF: OpenColorProfileW(x,x,x,x)+112 j
.text:73AA3AA2 push esi ; dwBytes
.text:73AA3AA3 mov [ebp+var_C], esi
.text:73AA3AA6 call MemAlloc(x) ; 分配固定长度0x104字节的堆
.text:73AA3AAB mov edi, eax
.text:73AA3AAD test edi, edi
.text:73AA3AAF mov [ebp+lpString1], edi
.text:73AA3AB2 jz short loc_73AA3A9B
.text:73AA3AB4 lea eax, [ebp+var_C]
.text:73AA3AB7 push eax ; PDWORD
.text:73AA3AB8 push edi ; PWSTR
.text:73AA3AB9 push 0 ; PCWSTR
.text:73AA3ABB call GetColorDirectoryW(x,x,x) ; 获取路径
.text:73AA3AC0 push offset _gszBackslash ; "\\"
.text:73AA3AC5 push edi ; lpString1
.text:73AA3AC6 mov edi, ds:lstrcatW(x,x)
.text:73AA3ACC call edi ; lstrcatW(x,x)
.text:73AA3ACE push dword ptr [ebx+0Ch] ; 这里就是蓝框中的字符串,只不过变成了UNICODE格式,所以长度成了原来的2倍。
.text:73AA3AD1 push [ebp+lpString1] ; lpString1
.text:73AA3AD4 call edi ; lstrcatW(x,x) ;这里可以溢出堆
.text:73AA3AD6 push dword ptr [ebx+0Ch] ; pMem
.text:73AA3AD9 call MemFree(x)
.text:73AA3ADE mov eax, [ebp+lpString1]
.text:73AA3AE1 mov [ebx+0Ch], eax
.text:73AA3AE4 mov [ebx+10h], esi
.text:73AA3AE7 jmp loc_73AA1EAE
.text:73AA3AEC ; ------------------------------------------------------------------------
上边的拷贝函数可以把0x208字节的字符串拷贝到0x104字节的堆中,因此可以覆盖下一个堆块的管理结构。
总结下:这个漏洞产生的根本原因是程序员对Unicode字符串长度进行了错误的理解,这让我想起了MS06-040。
本人菜鸟一只,请指教,谢谢。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课