freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

小试牛刀之CVE-2010-2883
2020-04-26 09:00:39

前言

近来正在学习《漏洞战争》,也是头一回分析二进制漏洞,花了好大一番功夫才搞明白,便想记录下过程。

初次分析,若有不正之处,还请多多指教。

分析环境

Windos XP & Ollydbg & Immunity debugger & IDA Pro & Adobe Reader 9.3.4

分析过程

1.定位漏洞点

根据书中给出的信息,漏洞存在于CoolType.dll中,使用IDA Pro反编译CoolType.dll,找到字符串 "SING" ,使用交叉引用功能定位到漏洞代码附近

但造成漏洞的主要原因是strcat,Adobe Reader在调用strcat时,未对uniqueName字段的字符串长度进行检测,导致可以将任意长度的字符串复制到固定大小的栈空间中,最终导致栈溢出。(摘抄自《漏洞战争》)

2.如何控制EIP

知道从哪可以复制数据到栈中导致栈溢出后,下一步就该考虑该复制多少数据进去才能控制eip。

使用ollydbg附加adobe reader,在0x803DDAB处,也就是call strcat的位置下断点。

使用msf生成样本文件,随后用adobe reader打开,同时触发断点。

执行F8,数据被复制到栈中,目的地址为0x12E4D8

使用immunity debugger的mona插件生成溢出字符串,并复制该字符串到0x12E4D8的位置。

至于为什么是溢出字符串的长度为什么是572字节,其实这里我是抄样本里的数据长度。尝试过用500字节会覆盖函数的返回地址,但并非当前函数,使用600、1000、1200都会触发STACK_BUFFER_OVERRUN异常。主要是想搞明白书中的内容,所以这里也用572字节。

执行F9,触发异常,但此处并未能覆盖EIP

异常信息显示,无法访问[6B413187],为了消除影响,通过计算偏移找到6B413187的位置,然后使用一个可读写的内存地址去替换它。

但如果直接拿6B413187去计算偏移的话是算不出来的,原因在于6B413187并不在我们生成的溢出字符串中。而EAX来源于[ECX+1C],应该拿ECX中的值去计算偏移才对。

找到偏移0x130的位置,将6B41316B替换成一个读写的内存地址,比如0x4A8A08E2,这是书中给出的地址,也可替换成其他的。(0x130也就是十六进制的304)

重新调试,将修改后的溢出字符串再次复制到缓冲区。(缓冲区的起始地址是0x12E4D8,被修改的位置在0x12E608,也就是0x12E4D8+0x130)

执行F9,再次触发异常,且成功覆盖EIP

再次使用immunity debugger的mona插件去计算偏移

重启调试进程,执行完0x803DDAB的call strcat后,在0x12E4D8+0x1F8的位置设置内存断点(0x1F8也就是504的十六进制)

F9继续执行,执行到第三次断点,找到能覆盖EIP的指令。

3.分析ShellCode

知道如何控制EIP后,继续来分析样本中的ShellCode。

重启调试进程,执行完0x803DDAB的call strcat后,在0x12E6D0的位置设置内存断点

 多次F9执行到0x808B308,也就是call dword ptr ds:[eax]

F7单步执行call dword ptr ds:[eax],跟入0x4A80CB38

此时的ESP的值为0x12DD24,而溢出字符串的位置在0x12E4D8。shellcode中通过ADD EBP,794; LEAVE;回到原来的栈空间中去。

F7继续执行

而用来绕过DEP的ROP指令和shellcode都存放在堆中,使用POP ESP修改ESP的值为0x0C0C0C0C

F7继续执行到ESP=0x0C0C0C1C,EIP=4A801F90的位置,前面那几条ROP指令暂不清楚作用是什么,尝试过替换掉成其他无意义的指令和去除这几条指令,shellcode依旧能正常运行。

而0x4A801F90正是关键的ROP指令之一,除此之外还有0x4A80B692

EAX中的值指向icucnv36.dll的IAT表,通过提前构造好栈中的参数,再利用POP EAX; JMP DWORD PTR DS:[EAX] 实现函数调用。后面几个函数的调用都是使用这种思路。

第一次调用了Kernel32.CreateFileA函数,其参数为

但后面调用的函数需要用到前一个函数的返回值,shellcode通过以下三条ROP指令将上一个函数的返回值放到下一个函数的参数列表中。

ROP1: XCHG EAX,EDI,此时EAX中存放的正是上一个函数的返回值。

ROP2: POP EBX,EBX中的值将参下一条ROP指令的计算。

ROP3: AND DWORD PTR SS:[EBX*2+ESP],EDI,这里才是将返回值放到参数列表的指令。

第二个调用的函数为Kernel32.CreateFileMappingA,参数列表如下

运用同样的手法调用第三个函数Kernel32.MapViewOfFile,参数列表如下

第四个函数为MSVCR80.memcpy,参数列表如下。位于ESP中的值(0x4F70000)为函数返回地址,也就是Shellcode的位置。

至此,整个shellcode的布局思路也分析得七七八八了。

小结

接下来,讨论下分析过程中的几个问题。

1.为什么ROP指令的地址都在icucnv36.dll的地址空间

这点书中也提到,因为在Adobe Reader的各个版本上这个dll的地址都是不变的。通过对比win7和xp中的icucnv36.dll(同一adobe reader版本),发现只有icucnv36.dll没有开启REBASE,DEP,ASLR,且存在可读可执行的.text段和可读可写的.data段。

2.既然使用500个字节的溢出字符串也能覆盖EIP,那要怎么做才能成功执行shellcode呢?

直接使用POP ESP的地址覆盖返回地址,将ESP设为0x0C0C0C0C即可,后面的都一样了。(测试时并没有发现GS的影子)

3.ROP3中的AND DWORD PTR SS:[EBX*2+ESP],EDI能换成诸如mov、xor吗?

可以,但找不到,尝试过在icucnv36.dll中查找mov、xor、or等指令来替换and,但都找不到。但也许还有其他办法实现该功能。

参考资料

《漏洞战争》

《灰帽黑客》第四版 第12章

*本文作者:wnltc0,转载请注明来自FreeBuf.COM

# CVE # 二进制 # 漏洞战争
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者