20

小试牛刀之CVE-2010-2883

 4 years ago
source link: https://www.freebuf.com/vuls/231105.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

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

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

分析环境

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

分析过程

1.定位漏洞点

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

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

2.如何控制EIP

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

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

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

Mz2iA3b.jpg!web 执行F8,数据被复制到栈中,目的地址为0x12E4D8

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

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

QJfIBby.jpg!web

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

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

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

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

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

MBjM3mF.jpg!web 执行F9,再次触发异常,且成功覆盖EIP

IzyYbu6.jpg!web

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

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

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

Mnae2qj.jpg!web

3.分析ShellCode

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

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

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

NnyQzmi.jpg!web F7单步执行call dword ptr ds:[eax],跟入0x4A80CB38

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

Ajyi6nb.jpg!web F7继续执行

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

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

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

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

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

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

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

VFj6Nbv.jpg!web

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

vMbqUvU.jpg!web

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

UVBjQzR.jpg!web

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

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

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

r26be2I.jpg!web 至此,整个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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK