吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 35875|回复: 43
收起左侧

[漏洞分析] CVE-2012-0158漏洞分析报告

  [复制链接]
Netfairy 发表于 2016-1-3 16:05
实验环境
操作系统:Vmware Windows xp sp1
Office版本:Microsoft OfficeWord 2003 (11.5604.5606)
漏洞文件:MSCOMCTL.OCX 6.1.95.45
调试器:Windbg:6.12.0002.633 x86
前言
Cve-2012-0158漏洞出现在MSCOMCTL.OCX,是微软Office系列办公软件在处理MSCOMCTLListView控件的时候由于检查失误,导致攻击者可以通过构造恶意的文档执行任意代码,本文我将分析这个漏洞的起因。
漏洞验证
我从网上拿到了一个样本:May.doc。首先我在虚拟机Word打开这个样本,
image1.png
计算器弹出来,接着Word就退出了。但我再一次打开这个样本,发现程序报错。
image2.png
所以在测试前记得先备份,因为下面我们多次要打开这个样本。

漏洞分析
打开样本弹出计算器,所以Shellcode应该会调用WinExec函数。用Windbg附加WINWORD.EXEbp kernel32!WinExec下断
image3.png
然后运行,把样本拖进word
image4.png
程序断在WinExec入口点。这时候计算器还没弹出来,看一下WinExec的参数,发现是a.exe。我去到这个目录,发现它就是一个计算器。
看来shellcode应该是把系统的calc复制到别的目录再运行它。
image5.png
WinExec的返回地址是0x00127dee。往上翻翻,没发现shellcode从哪开始。Kb打印堆栈
[Asm] 纯文本查看 复制代码
ChildEBP RetAddr  Args to Child             
00127b20 00127dee 0cd5a5b0 00000000 0cd5a5b0 kernel32!WinExec
WARNING: Frame IP not in any known module. Following frames may be wrong.
00127b50 275c8a0a 07d8c008 0cd3b868 0001c000 0x127dee
00127b8c 00127c05 1005c48b c7000001 4d032400 MSCOMCTL!DllGetClassObject+0x41cc6
00000000 00000000 00000000 00000000 00000000 0x127c05
重新载入,在MSCOMCTL!DllGetClassObject+0x41cc0下断
image6.png
断在这个call的上一句,Kb发现这一层函数的返回地址是0x 275e701a,它前面一个call
image7.png
接着两次p,然后搜索内存
image8.png
0x00127b88发现万能跳转0x7ffa4512shellcode。并且在
275c8a05 e863fdffff      call   MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)
之前这里还没有被shellcode覆盖,显然,溢出发生在
275c8a05 e863fdffff      call   MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)

接着上面,我单步执行
image9.png
image10.png
是不是很熟悉呢?,到这里我们知道的信息如下:

[Asm] 纯文本查看 复制代码
Shellcode执行发生在下面call返回
275e7015 e8ad19feff      call    MSCOMCTL!DllGetClassObject+0x41c83 (275c89c7)
溢出发生在
[Asm] 纯文本查看 复制代码
275c8a05 e863fdffff      call    MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)
Shellcode通过jmp esp覆盖返回地址利用。顺便dump部分shellcode
[Asm] 纯文本查看 复制代码
00127b88 12 45 fa 7f 90 90 90 90 90 90 90 90 8b c4 05 10  .E..............
00127b98 01 00 00 c7 00 24 03 4d 08 e9 5a 00 00 00 6b 65  .....$.M..Z...ke
00127ba8 72 6e 65 6c 33 32 00 df 2d 89 8c 1b 81 7d ef 42  rnel32..-....}.B
00127bb8 9d 85 85 d6 4e 99 59 5a 61 d8 54 93 77 77 21 9d  ....N.YZa.T.ww!.
00127bc8 4a 62 68 c3 53 a3 83 6a 6b df 5c 5a 8a 1d 2b 4f  Jbh.S..jk.\Z..+O
00127bd8 2c 45 28 81 71 f5 40 01 92 8f 05 ba 36 c1 0a 61  ,E([email].q.@.....6..a[/email]
00127be8 61 61 61 73 68 65 6c 6c 33 32 00 8b 98 8a 31 61  aaashell32....1a
00127bf8 61 61 61 6f 70 65 6e 00 e8 11 02 00 00 6a ff e8
接下来用IDA打开有漏洞的MSCOMCTL.OCX。定位前面那两个关键call,先看上层call
[Asm] 纯文本查看 复制代码
275e7015 e8ad19feff      call    MSCOMCTL!DllGetClassObject+0x41c83 (275c89c7)
image11.png
首先分配20个字节空间
275C89CA sub     esp, 14h        ; 分配20字节局部空间
然后调用
275C89DA call    sub_275C876D   
这个call的功能是从样本读取dwBytes,这里是0CH字节返回到eax指向的内存地址。读取到的0xC字节如下所示:
00127b70 43 6f 62 6a 64 00 00 00 82 82 0000

接着程序
image12.png
如果读取的12字节开始4个字节不等于0x6A626F43h,则跳转到错误处理。否则执行
image13.png
275C89F3 cmp     [ebp+dwBytes], 8

我这里[ebp+dwBytes]0x00008282。显然0x00008282大于8,所以程序转到
image14.png
这里其实就是我们真正溢出的那个CALL。我们看这个call有三个参数
Sub_275C876D8字节局部空间起始地址,lpMem,字节数) 【这里字节数是0x8282

跟进这个call看看,首先
[Asm] 纯文本查看 复制代码
275c877f 6a04         push    4
275c8781 51           push    ecx
275c8782 53           push    ebx
275c8783 ff500c        call  dword ptr [eax+0Ch]  ole32!CExposedStream::Read (771ca84b)}
读取4个字节到[ebp+var_4],返回值和0比较,如果小于0,读取失败,转到失败处理,否则
image15.png
[ebp+var_4][ebp+dwBytes]0x00008282比较,相等则
image16.png
分配0x8282字节空间,接着
image17.png
读取0x8282字节到刚才分配的堆空间。接着
image18.png
image19.png
我们看到:275C87CB rep movsd  再看看此时的
EDI=0x127b7c
ESI=0x20e008 (指向前面读取的0x8282字节)
ECX=0x20a0
而我们看
275e7015 e8ad19feff      call   MSCOMCTL!DllGetClassObject+0x41c83 (275c89c7)

函数的返回地址是0x127b88
image20.png
所以这里的意思就是把从样本中读取的的0x8282字节复制0x82800x127b7c,上层函数的返回地址是0x275c8a0a。上上层函数的返回地址在0x127b88。所以
275C87CB rep movsd 所在的这层函数在溢出后能正常返回,上上层函数在返回时候才跳去执行shellcode。分析完成,我们看到其实漏洞发生的根本原因在于
.text:275C89F3 cmp     [ebp+dwBytes], 8
.text:275C89F7 jb      loc_275D
比较从样本读取过来的数据时候处理错误,这里应该是大于8个字节就转到错误处理,它写成了小于8个字节转到错误处理。而这个字节大小是我们可以控制的,所以当我们传递比如0x8282,那么程序就会读取样本相应位置可控的0x8282字节到堆空间,然后把这0x8282字节复制到0x127b7c地址,进而覆盖掉函数的返回地址,执行我们的shellcode。漏洞原因伪代码表示如下:
[C] 纯文本查看 复制代码
#include <stdio.h>
int main()
{
         sub_275C89C7();
         return 0;
}
sub_275C89C7()
{
         char temp[20];  //分配20字节局部空间
         Read(temp,12);  //从样本读取12字节到temp
         if(temp[0]==0x6A626F43)
         {
                   if(temp[8]<8)  //关键
                   {
                            exit(-1);
                   }
                   else
                   {
                            sub_275C876D(temp[8],lpMen,*temp[8])
                   }
         }
         else
         {
                   exit(-1);
         }
}
 
sub_275C876D(temp[8],lpMen,*temp[8])
{
         char val[4];
         if( Read(val,4) <0 );  //继续从样本读取4字节到temp
         {
                   exit(-1);
         }
         else
         {
                   if(val[0]==*temp[8])
                   {
                            if( buffer=HeapAlloc(hHeap,0,val[0]) );  //分配temp[0]字节空间
                            {
                                     Read(buffer,val[0]);  //从样本读取temp[0]字节到临时空间
                                     memcpy(temp[12],buffer,0x8280);  //复制0x8280字节到sub_275C89C7()剩下的8字节空间,导致覆盖返回地址
                            }
                            else
                            {
                                     exit(-1);
                            }
                   }
                   else
                   {
                            exit(-1);
                   }
         }
        
}

漏洞利用
此样本是通过用jmp esp地址覆盖函数返回地址进行利用的
image21.png
搜一下样本,发现shellcode
image22.png
之前看了通过利用异常处理进行的利用。就像试试这个漏洞能不能用此方法。在溢出即将发生时候
[Asm] 纯文本查看 复制代码
275c87cb f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
dump异常链
[Asm] 纯文本查看 复制代码
0:000> !exchain
0012f908: USER32!_except_handler3+0 (77d3edbf)
  CRT scope  0, func:   USER32!UserCallWinProcCheckWow+155 (77d4f0cc)
0012f968: USER32!_except_handler3+0 (77d3edbf)
0012ffb0: WINWORD!wdGetApplicationObject+27bcf8 (30a6c5d4)
0012ffe0: kernel32!_except_handler3+0 (77e74809)
  CRT scope  0, filter: kernel32!BaseProcessStart+29 (77e737c8)
                func:   kernel32!BaseProcessStart+3a (77e80128)
Invalid exception stack at ffffffff
此时EDI=0x00127b7c,复制33408字节,最多覆盖到0x12FDFC,而最近的异常处理在0x12f908
理论上可以利用。但是当我修改样本shellcode后面的数据时shellocde后面的数据在复制前已经不是原始的的了。所以尽管可以覆盖到SEH,但数据似乎是不可控的。

总结
这是我分析的第一个CVE,以前都是看书,写写demo调试,基本就是strcpy那种简单的溢出。看别人分析的CVE又看不懂。自己分析完一个,感觉收获蛮大,了解到其实CVE漏洞也没有那么神秘高深,还有漏洞居然还能这样产生,而不是strcpy,memcpy造成溢出,居然是一个小小的判断失误就导致了漏洞,真是千里之堤溃于蚁穴。这个漏洞是由于MSCOMCTL.OCX在解析数据的时候将需要处理的数据拷贝到栈上,而对需要拷贝的数大小未做正确检查,造成标准的栈溢出漏洞。

免费评分

参与人数 20吾爱币 +4 热心值 +20 收起 理由
Gh0stRo2kie + 1 + 1 谢谢@Thanks!
itking024 + 1 + 1 谢谢@Thanks!
lrvy + 1 + 1 谢谢@Thanks!
MXWXZ + 1 + 1 好文章!不过现在的系统有UAC,有各式杀软有溢出也很难造成破坏。
有侠 + 1 热心回复!
菜鸟也想飞 + 1 谢谢@Thanks!
Nutural + 1 我很赞同!
A-_虚伪_! + 1 虽然看不懂 但是知道比我厉害
wogeshange + 1 我很赞同!
woainiheibao + 1 我很赞同!
sxhytds + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
noblesport + 1 我很赞同!
康小泡 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
Sound + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
aikuimail + 1 楼主能吃苦,技术好,祝早成大神。
expasy + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
Zde_Hui + 1 看不懂.... 以资鼓励 不能让好帖埋.
478906808 + 1 我很赞同!
w1107436701 + 1 虽然我看不懂
Niuer + 1 有意义的帖子

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

谜一样的帅 发表于 2016-10-6 09:03
这个漏洞,感觉不好利用。他允许注入的代码好短,要做到yuange说的那种能“完美打开完美推出”真感觉不好执行啥,而且有个红叉,别人一看就知道被干了。。。。。
隐藏和使用都好无力
 楼主| Netfairy 发表于 2016-1-5 12:11
pengcan 发表于 2016-1-5 10:45
赞一个 写的很详细,想问下LZ样本在哪找的。。搜了好久没搜到

找POC我一般通过https://www.exploit-db.com metasploit binvul,或者搜索引擎
丶懒喵喵 发表于 2016-1-3 16:13
学霸 发表于 2016-1-3 16:16
小白,看不懂~也不想看懂。
 楼主| Netfairy 发表于 2016-1-3 16:22
漏洞分析的文章,看不懂或者不感兴趣的略过即可
水天下 发表于 2016-1-3 16:32
好的溢出方法
Sound 发表于 2016-1-5 01:55
有心, 挺详细, 楼主辛苦

PS: 这个漏洞记得挺久了。作为一个学习的好材料。
pengcan 发表于 2016-1-5 10:45
赞一个 写的很详细,想问下LZ样本在哪找的。。搜了好久没搜到
pengcan 发表于 2016-1-5 13:06
多谢LZ 已经找到啦
m0cha 发表于 2016-1-6 04:28
好厉害啊,虽一开始然不是很懂,但是多看看还是蛮有收获的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-25 23:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表