邪恶八进制信息安全团队技术讨论组's Archiver

sunwear 2005-12-17 14:43

[转载]金山词霸的"溢出"问题

文章作者:cocoruder
信息来源:安全焦点技术论坛

author:cocoruder
date:15/12/2005

sowhat的漏洞报告[url]http://www.nsfocus.net/vulndb/7069[/url]
偶在使用金山词霸的时候也遇到过这种问题,造成系统假死机,本以为真是个溢出问题,或许可以利用利用,写一大段E文诱惑某人来看:),于是在假死机的状态下呼出Softice,发现堆内存被疯狂申请,最终确定只是个内存泄露问题:P,下面给出细节。偶测试的版本是金山词霸2003,点帮助后显示的版本信息为6.0.0.0。

金山词霸主程序xdict.exe负责与其注射到每个进程里的插件(Cjktl32.dll)通信,获取取得的字符,并进行处理。
问题出现在xdict.exe的sub_44e3b0函数中,如下:

[code].text:0044E3B0            sub    esp, 9Ch
.text:0044E3B6            push   ebp
.text:0044E3B7            push   esi
.text:0044E3B8            push   edi
.text:0044E3B9            mov    edi, ecx
.text:0044E3BB            xor    ebp, ebp
.text:0044E3BD            mov    [esp+0A8h+var_84], edi
.text:0044E3C1            mov    eax, [edi+48h]
.text:0044E3C4            cmp    eax, ebp
.text:0044E3C6            jz    short loc_44E3D7
.text:0044E3C8            mov    eax, [eax]
.text:0044E3CA            cmp    eax, ebp
.text:0044E3CC            jz    short loc_44E3D7
.text:0044E3CE            push   eax              ; BSTR
.text:0044E3CF            call   ds:SysStringLen      ;求取词长度
.text:0044E3D5            jmp    short loc_44E3D9
...
.text:0044E4CA            mov    ecx, edi
.text:0044E4CC            mov    esi, eax
.text:0044E4CE            call   sub_44D560      ;这个call根据取词Buff计算SumTableCode大小
...
.text:0044E578 loc_44E578:                         ; CODE XREF: sub_44E3B0+158j
.text:0044E578            mov    eax, [edi+5D8h]
.text:0044E57E            mov    edx, [esp+0ACh+var_7C]
.text:0044E582            sub    eax, ebp
.text:0044E584            cmp    edx, eax        ;SumTabldeCode与一固定值比较,大于等于则跳
.text:0044E586            jge    short loc_44E5ED
...
...
.text:0044E5ED loc_44E5ED:                         ; CODE XREF: sub_44E3B0+1D6j
.text:0044E5ED            mov    ebp, [esi+38h]
.text:0044E5F0            mov    esi, [esi+3Ch]
.text:0044E5F3            mov    edi, [esp+0ACh+var_94]
.text:0044E5F7            mov    ecx, [esp+0ACh+var_84]
.text:0044E5FB            push   esi
.text:0044E5FC            push   ebp
.text:0044E5FD            push   edi
.text:0044E5FE            push   eax
.text:0044E5FF            mov    [esp+0BCh+var_80], esi
.text:0044E603            call   sub_44E970          ; 拷贝当前取词并拷贝至1堆内存,并取得0x0000结尾,
.text:0044E603                                ; 正常应返回内存Unicode字节数,异常返回0
.text:0044E608            add    eax, ebp
.text:0044E60A            mov    [esp+0ACh+var_88], eax
.text:0044E60E            lea    ecx, [eax-1]      ;ecx=-1
.text:0044E611            cmp    ecx, esi        ;
.text:0044E613            jge    loc_44E70C      ;小于,不跳
.text:0044E619            mov    [esp+0ACh+var_24], edi
.text:0044E620            jmp    short loc_44E626      ;进入堆内存申请代码
.text:0044E622 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0044E622
.text:0044E622 loc_44E622:                         ; CODE XREF: sub_44E3B0+350j
.text:0044E622            mov    eax, [esp+0ACh+var_88]   ; 进入1次,分配一次堆内存。
.text:0044E626
.text:0044E626 loc_44E626:                        
.text:0044E626            mov    esi, [ebx+8]
.text:0044E629            mov    edx, [esp+0ACh+var_9C]
.text:0044E62D            dec    eax
.text:0044E62E            push   0FFFFFFFFh
.text:0044E630            lea    ecx, [esi+1]
.text:0044E633            mov    [esp+0B0h+var_1C], eax
.text:0044E63A            mov    eax, [esp+0B0h+var_8C]
.text:0044E63E            push   ecx
.text:0044E63F            mov    ecx, ebx
.text:0044E641            mov    [esp+0B4h+var_20], ebp
.text:0044E648            mov    [esp+0B4h+var_18], edx
.text:0044E64F            mov    [esp+0B4h+var_14], eax
.text:0044E656            call   sub_426B60          ; 这个函数分配了堆内存
...
.text:0044E6D8            push   ecx
.text:0044E6D9            mov    [esp+0B0h+var_8C], ebp
.text:0044E6DD            mov    ebp, [esp+0B0h+var_88]
.text:0044E6E1            push   ebp
.text:0044E6E2            push   edi
.text:0044E6E3            push   edx
.text:0044E6E4            mov    ecx, esi
.text:0044E6E6            mov    [esp+0BCh+var_9C], 0
.text:0044E6EE            call   sub_44E970          ; 和0044e603处同样的函数,SumTableCode>0x1f8,返回0
.text:0044E6F3            mov    ecx, [esp+0ACh+var_80]
.text:0044E6F7            add    eax, ebp
.text:0044E6F9            mov    [esp+0ACh+var_88], eax
.text:0044E6FD            dec    eax
.text:0044E6FE            cmp    eax, ecx           ; sub_44e970返回0时eax=-1,跳,构成死循环
.text:0044E700            jl    loc_44E622
.text:0044E706            mov    edi, [esp+0ACh+var_94]
.text:0044E70A            mov    esi, ecx[/code]
程序先通过函数sub_44E970遍历取得的每个字符,并根据每个字符计算出一个SumTableCode值,这个值再和一固定值StaticCode相比较,大于等于则会进入sub_44E970子函数,此函数又比较了一遍SumTableCode和StaticCode,大于则认为出错,返回0。主函数在处理这个函数的返回值时出现错误(未考虑返回0的情况,直接减1=-1),导致进入死循环,不断分配堆内存,从而导致内存泄露。

sub_44E970子函数里计算SumTableCode的算法简要:
[code]for (i=0;i<sizeof(plain)-1;i++)
{   
   SumTableCode=SumTableCode+BaseTable[plain[i]*3*4]+BaseTable[plain[i]*3*4+4]+BaseTable[plain[i]*3*4+8]
}[/code]

BaseTable为一大数据表(附在后面),plain为取词缓冲区。

也就是说,SumTableCode>StaticCode就会跳到死循环中产生内存泄露,偶的机器的StaticCode恒为0x1f8,查表字符A对应的
   BaseTable[plain[i]*3*4]+BaseTable[plain[i]*3*4+4]+BaseTable[plain[i]*3*4+8]=9
因此要输入至少0x1f8/9+1=57个&#39;A&#39;字符才能触发内存泄露,56个&#39;A&#39;也不会触发。

另外的一个可能是真正的溢出问题出现在其取词插件Cjktl32.dll模块中,由于触发次数有限,暂时还未得到细节:P

附:
dump出来的BaseTable

[code]"\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
"\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00"
"\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
"\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00"
"\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
"\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00"
"\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
"\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x0B\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0A\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x03\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00"
"\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00"
"\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x0D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0A\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x07\x00\x00\x00"
"\x01\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x0C\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x0B\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x09\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x0B\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x0D\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x0A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0A\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x08\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00"
"\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
"\x05\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x03\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x0B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00"
"\xFF\xFF\xFF\xFF\x08\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00"; [/code]

页: [1]
© 1999-2008 EvilOctal Security Team