发帖前在论坛搜索了一下,怕有重复就不好了。发现这篇(Foxit阅读器栈缓冲区溢出egghunter方法),没来得及细看,似乎是说的同一个漏洞,不过是翻译过来的介绍怎么fuzz测试出这个漏洞的,还好我可以断续。

最近得到一个样本(bhk.py),这是样本中的描述信息:
#**************************************************************************
# Exploit Title : Foxit 4.1.1
# Date          : 13/11/2010
# Author        : Sud0
# Bug found by  : dookie
# Original POC  : https://www.exploit-db.com/exploits/15514/
# Software Link : http://www.foxitsoftware.com/downloads/index.php
# Version       : 4.1.1
# OS            : Windows
# Tested on     : XP SP3 En (VirtualBox)
# Type of vuln  : EIP / SEH
# Thanks to my wife for her support
# Greetz to: Corelan Security Team
# Greetz to: dookie for finding the bug
# Thanks to offsec for the Exploit Week End challenge
# http://www.corelan.be:8800/index.php/security/corelan-team-members/
# writeup : http://www.corelan.be:8800/index.php/2010/11/13/offensive-security-exploit-weekend/
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
感谢dookie及Sudo的分享。我根据这个样本调试分析了一下该漏洞,跟踪出最初出问题的地方是lstrcpyw拷贝字符串时覆盖了函数返回地址,下面是分析过程,欢迎大家讨论。

1.  样本测试
首先阅读了一下样本代码,比较简单,就是定义了几个字符串,然后把它们全部写入文件成为样本pdf,不过样本中值得注意的一点是注释中提及利用了SEH跳转到Shellcode。
好的,运行脚本得到Foxit-exploit.pdf,开虚拟机运行FoxitReader相应版本,OD附加,注意设置OD调试选项,不忽略任何异常,同时如果用了StrongOD插件的话,也注意StrongOD的选项中有个“skip some exceptions”,不要勾选,我一开始调试时就是因为这个选项,直接到了利用成功,OD也没有异常中断下来,让我还以为样本没有利用SEH来跳转…. 嗯,这也算帮我多熟悉了一点StrongOD吧。 然后打开样本pdf,FoxitReader就异常中断到OD了。
异常指令地址为0x00410048,同时观察一下栈窗口,发现esp附近全是0x0041,也就是A的Unicode码,回想起bhk.py中的”junk = "A"*540”,看来这是被覆盖了的栈区。观察一下栈区,没有什么明显的返回地址什么的,很长一段都是Unicode字串。看来样本覆盖了太多的栈区,现在想从栈中得到问题函数(拷贝数据到栈中导致栈被破坏的函数)被调用前最近的一些函数的线索(主要是返回地址)是不可能了,怎么办呢??

先去异常处理函数0x006a0046看下吧,pop pop ret,没什么 问题,典型的利用异常跳转到Shellcode的利用方式。如果要分析一下Shellcode,那么bp 0x006a0046、shift+F9然后单步就一切了然,这不是这里要讨论的,其实对于这个样本也没有什么定位Shellcode的需要,利用程序(bhk.py)中不是都写明了Shellcode嘛。不过利用程序中的align、control所对应的汇编代码还是有一定参考价值的,演示了成功利用漏洞所应控制的细节方面。


 

2.  变得有趣之前
这里我不是想要定位并分析Shellcode, 而是想要了解到底是什么原因导致程序跳转去shellcode的,现在我们已经知道这是一个栈溢出了,什么地方导致了栈溢出呢?
从OD异常中断的地方入手吧,异常地址为0x00410048,且异常时esp附近规规整整地排好了0x00410041,嗯…推断一下前几步程序的执行,我们有理由相信一个函数返回到了0x00410041,几步后,砰…异常了。真的是这样的。
好的,既然我们想在这个时候挖掘一点问题函数前面几个函数的信息,而保存这些信息的栈区被我们这个样本的数据覆盖了,我们要程序触发异常,却要保留这些信息,怎么办?好的,我这里是这样操作的…
我改短了用于覆盖栈区的数据的长度,用记事本打开Foxit-exploit.pdf,在文件结尾处可以看见我们的覆盖数据,大量的’A’加大量的“无意义数据”,根据上面图中反映的情况,我们把覆盖数据后10个’A’和后面的“无意义数据”去掉吧,不一定是10个,反正大概算一下,使得数据既能覆盖返回地址(上图中的esp-4)又少覆盖栈中数据即可,改后保存为文件crash.pdf。
同样的调试步骤,这次打开文件crash.pdf,异常中断到OD时栈区为这样:
 


怎么样,去0x96f6e6看看吧,
0096F6DE  |.  56            push    esi
0096F6DF  |.  8BCF          mov     ecx, edi
0096F6E1  |.  E8 A7330000   call    00972A8D
0096F6E6  |.  8BC7          mov     eax, edi
0096F6E8  |.  5F            pop     edi
0096F6E9  |.  5E            pop     esi
0096F6EA  \.  C2 0400       retn    4
Ctrl+F2重新运行调试程序,F9让程序运行,界面完全出现后,bp 0x0096F6E1… 唉,这里怎么说呢,反正有兴趣的朋友去实际试试吧,在0x00972A8D这个函数体内,很多地方尝试下断,程序都会一直断,可能我们真是走错地方了。
没关系,在数字迷宫中摸爬,我已习惯了头破血流,哈… 几次尝试后(几十次?it doesn’t matter)我决定退一步看看,0x00979905:
009798F9  |> \8B10          |mov     edx, dword ptr [eax]
009798FB  |.  6A 01         |push    1
009798FD  |.  8BC8          |mov     ecx, eax
009798FF  |.  FF92 E0000000 |call    dword ptr [edx+E0]
00979905  |.  43            |inc     ebx
00979906  |>  837D FC 00    |cmp     dword ptr [ebp-4], 0
0097990A  |.^ 75 B9         \jnz     short 009798C5
下断0x9798ff,嗯,怎么动FoxitReader都没断下,现在打开crash.pdf试试,砰,断下了,事情似乎发展得很顺嘛。F7去了0x00402e60
00402E60   .  6A FF         push    -1
00402E62   .  68 701D9A00   push    009A1D70               ;  SE 处理程序安装
00402E67   .  64:A1 0000000>mov     eax, dword ptr fs:[0]
00402E6D   .  50            push    eax
00402E6E   .  64:8925 00000>mov     dword ptr fs:[0], esp
00402E75   .  83EC 18       sub     esp, 18
00402E78   .  8B4424 28     mov     eax, dword ptr [esp+28]
00402E7C   .  53            push    ebx
00402E7D   .  56            push    esi
00402E7E   .  57            push    edi
00402E7F   .  8BD9          mov     ebx, ecx
00402E81   .  50            push    eax
00402E82   .  E8 04415800   call    00986F8B
00402E87   .  E8 74110700   call    00474000
00402E8C   .  8BF8          mov     edi, eax
00402E8E   .  85FF          test    edi, edi
00402E90   .  897C24 14     mov     dword ptr [esp+14], edi
00402E94   .  0F84 6B010000 je      00403005

00402E82 处步过的时候程序异常了,重新来过,这次在这里F7,进去0x00986F8B,上下打量一翻,一个“可爱”的函数映入了眼帘:lstrcpyW,接下来的分析验证就简单了,经过确认,事故责任人就是它….

上传的附件 样本及分析.rar(解压密码:pediy)