❽⁄₇ ⟦ OSCP ⬖ 研记 ⟧ 修改漏洞利用脚本 ➱ 深入剖析JMP ESP原理

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

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

🌌 立即前往 👉 🚀

▶ 信息收集

▶ 漏洞检测

▶ 初始立足点 ➢ 深入剖析JMP ESP原理 ➢🔥🔥🔥

▶ 权限提升

▶ 横向移动

▶ 报告/分析

▶ 教训/修复

目录

1.ESP寄存器在函数返回时的特殊位置

[1.1 复习核心载荷结构](#1.1 复习核心载荷结构)

[1.1.1 再次复习 Python 漏洞利用代码 (42928.py)](#1.1.1 再次复习 Python 漏洞利用代码 (42928.py))

[1.1.1.1 核心载荷分析](#1.1.1.1 核心载荷分析)

[1.1.2.2 POST请求构造](#1.1.2.2 POST请求构造)

[1.2 核心问题剖析](#1.2 核心问题剖析)

[1.2.1 完整的原理剖析](#1.2.1 完整的原理剖析)

[1.2.1.1 构造恶意数据](#1.2.1.1 构造恶意数据)

[1.2.1.2 栈内存状态变化图](#1.2.1.2 栈内存状态变化图)

[1.2.1.3 详细执行流程](#1.2.1.3 详细执行流程)

[1.2.2 如何找到JMP ESP指令地址?](#1.2.2 如何找到JMP ESP指令地址?)

方法1:在系统DLL中搜索

方法2:使用已知通用地址

方法3:通过调试器获取

[1.2.3 执行时间线与ESP变化(重要)](#1.2.3 执行时间线与ESP变化(重要))

[1.2.3.1 详细的内存布局图](#1.2.3.1 详细的内存布局图)

[1.2.3.2 执行流程验证](#1.2.3.2 执行流程验证)

[1.2.3.3 形象比喻](#1.2.3.3 形象比喻)

①快递中转站

②地铁换乘系统

[1.2.3.4 技术细节:寄存器状态变化](#1.2.3.4 技术细节:寄存器状态变化)

[1.2.4 防御视角:如何阻止这种攻击](#1.2.4 防御视角:如何阻止这种攻击)

[1.3 总结核心要点](#1.3 总结核心要点)

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


1.ESP寄存器在函数返回时的特殊位置

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

之前的一系列文章写的是,如果寻找漏洞利用的脚本,并利用缓冲区溢出原理加以利用,按照实际测试环境的情况修改脚本后编译为可执行文件,最终拿到反向shell。主要要非常了解栈结构、出入栈原理,以及shellcode的结构等。但,这里有一个核心问题不知道你们有没有想过:

① "为什么覆盖了返回地址后,当执行漏洞利用文件时,返回地址指向的不是shellcode的地址,而是JMP ESP指令?"

② "为什么返回地址指向JMP ESP指令,就能执行我们的shellcode?"

至少,我脑袋中想到了这个很细节、但有非常核心的问题!那么,我们试试把它弄懂。


1.1 复习核心载荷结构

1.1.1 再次复习 Python 漏洞利用代码 (42928.py)

在此复习42928.py源代码,开始进行分析。

​


1.1.1.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]

1.1.2.2 POST请求构造

漏洞利用通过HTTP POST的请求体携带来发送恶意载荷:

​

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

1.2 核心问题剖析

"++为什么返回地址指向JMP ESP指令,就能执行我们的Payload?++"

1.2.1 完整的原理剖析

1.2.1.1 构造恶意数据
复制代码
攻击数据结构:
[低地址] [填充数据] [JMP ESP地址] [NOP滑块] [Payload] [剩余填充] [高地址]
         ↑              ↑              ↑         ↑
     填满缓冲区    覆盖返回地址    安全缓冲    恶意代码
1.2.1.2 栈内存状态变化图
复制代码
函数返回前栈布局:
高地址
├─────────────────┤
│    Payload      │ ← 实际在返回地址之后
├─────────────────┤
│    NOP滑块      │
├─────────────────┤ ← ESP移动到这里(ret执行后)
│  JMP ESP地址    │ ← 返回地址(被覆盖)
├─────────────────┤ ← ESP初始位置(ret执行前)
│    填充数据      │
│   (缓冲区)     │ ← 类似780个A来做填充
低地址
1.2.1.3 详细执行流程

为什么这样设计?------ 解决Payload地址不确定问题

问题根源

  • 栈地址可能变化(不同系统、不同运行环境)

  • 攻击者无法精确知道Payload在目标栈中的确切地址(解决的核心痛点)

  • 直接硬编码Payload地址成功率极低

🧩 JMP ESP的巧妙之处!!!

复制代码
固定地址问题解决方案:
┌─────────────────────────┬─────────────────────────────┐
│       直接跳转方案       │        JMP ESP间接方案       │
├─────────────────────────┼─────────────────────────────┤
│ 需要知道Payload的精确地址 │ 只需要知道JMP ESP指令的地址   │
│ 地址随栈变化而变化        │ 地址在系统DLL中固定(无ASLR时)│
│ 成功率低                 │ 成功率高                     │
└─────────────────────────┴─────────────────────────────┘

1.2.2 如何找到JMP ESP指令地址?

方法1:在系统DLL中搜索
复制代码
# 示例:在Windows DLL中搜索JMP ESP指令(机器码FF E4)
# 使用调试器或专用工具搜索
JMP_ESP_ADDRESS = 0x75CB52CB  # kernel32.dll中的地址
方法2:使用已知通用地址
复制代码
常见系统JMP ESP地址(无ASLR时):
• Windows XP SP3: 0x7C86467B (kernel32.dll)
• Windows 7 SP1: 0x75C8E2E4 (kernel32.dll)
• Linux (特定版本): 可变,通常需要自定义
方法3:通过调试器获取
复制代码
1. 在目标环境运行调试器(如OllyDbg、GDB)
2. 加载目标程序
3. 搜索指令 "JMP ESP" 或机器码 "FF E4"
4. 记录找到的地址

1.2.3 执行时间线与ESP变化(重要)

布局方式 内存结构 执行结果 为什么
❌ 错误布局 [填充][恶意代码][JMP ESP地址] 攻击失败 ESP指向JMP ESP地址之后,但那里没有代码
✅ 正确布局 [填充][JMP ESP地址][恶意代码] 攻击成功 ESP指向恶意代码开始处
1.2.3.1 详细的内存布局图

正确布局(攻击成功)

复制代码
低地址
├─────────────────┤ ← 缓冲区起始
│   AAAA...AAAA   │ ← 填充数据 (填满缓冲区)
├─────────────────┤ ← 原返回地址位置
│   0x75CB52CB    │ ← JMP ESP指令地址 (4字节)
├─────────────────┤ ← ESP执行ret后指向这里!
│   0x90 0x90...  │ ← NOP滑块 (可选,增加容错)
├─────────────────┤
│   shellcode     │ ← 恶意代码 (Payload)
│   (恶意指令)     │
├─────────────────┤
│   更多填充...    │ ← 如果需要
└─────────────────┘
高地址

1.2.3.2 执行流程验证
复制代码
1. ret执行前: ESP → 0x75CB52CB (在栈中)
2. ret执行: 
   - EIP = 0x75CB52CB (JMP ESP指令地址)
   - ESP = ESP + 4 → 指向NOP滑块开始处
3. 执行JMP ESP:
   - EIP = ESP → 指向NOP滑块开始处
4. 执行NOP滑块 → 滑向shellcode
5. 执行shellcode → 攻击成功!

1.2.3.3 形象比喻
①快递中转站
  • 你(攻击者):要寄送一个秘密包裹(Payload)

  • 收件人(目标程序):住在经常搬家的公寓(栈地址变化)

  • 快递公司(程序执行流):必须把包裹送到正确地址

传统方法的困境

复制代码
你的计划:直接告诉快递公司"送到A公寓201室"
问题:收件人可能已经搬到B公寓302室
结果:包裹送错地方,任务失败 ❌

JMP ESP方案的巧妙

复制代码
你的新计划:
1. 告诉快递公司"先送到中央中转站"(JMP ESP地址)
2. 在中转站,有一个智能机器人(JMP ESP指令)
3. 机器人会问:"包裹接下来应该送到哪里?"
4. 快递员(ESP寄存器)回答:"哦,收件人刚刚告诉我,他现在在C公寓105室"
5. 机器人立即把包裹送到C公寓105室(ESP指向的地址)
6. 包裹准确送达,任务成功 ✅
②地铁换乘系统
  • 你(CPU):要去朋友家(执行正常代码)

  • 攻击者:想把你引导到秘密基地(执行Payload)

  • 地铁系统(程序执行流):有固定线路

正常路线(无攻击)

复制代码
你家 → 乘坐2号线 → 在**人民广场站**换乘 → 乘坐8号线 → 朋友家

攻击者的篡改

攻击者知道:

复制代码
1.人民广场站(JMP ESP地址) 的位置固定

2.从2号线换乘时,你会自动走到8号线站台(ESP指向的位置)

3.他可以在8号线站台放置引导员(NOP/Payload)

攻击实施

复制代码
1. 攻击者修改路线图:把"人民广场站"标记为必须换乘站
2. 你到达人民广场站(JMP ESP地址)
3. 车站广播(JMP ESP指令):"请前往您当前所在的站台"
4. 你已经在8号线站台(ESP指向NOP/Payload)
5. 站台上的引导员(NOP)带你到秘密基地(Payload)

为什么这招高明?

  • 攻击者无需知道秘密基地的确切地址

  • 他只需要知道人民广场站的固定位置

  • 地铁系统的换乘逻辑(ret指令) 会自动把你带到正确站台

  • 8号线站台总是在人民广场站之后(ESP总指向返回地址后)

为什么这个方案可靠?

  • 中转站地址固定:JMP ESP指令在系统DLL中,地址不变

  • 总是知道最新地址:ESP寄存器始终指向正确位置

  • 总是可用:JMP ESP指令在系统启动时就存在

📊 攻击成功的关键要素表

要素 要求 为什么重要
JMP ESP地址 必须准确且可执行 这是攻击的"跳板",必须可靠
ESP指向 必须指向NOP/Payload 确保跳转后能执行到恶意代码
缓冲区大小 必须精确计算偏移 确保JMP ESP地址覆盖正确位置
Payload位置 必须在返回地址之后 这样ESP才会指向它
无坏字符 避免\x00等特殊字符 防止数据被截断

1.2.3.4 技术细节:寄存器状态变化
复制代码
函数返回时刻的寄存器状态:
      执行ret前                执行ret后
EIP: 指向ret指令         EIP: JMP ESP指令地址
ESP: 指向返回地址        ESP: 返回地址+4(指向NOP开始)
EBP: 可能被覆盖          EBP: 可能已被破坏

关键计算:
返回地址偏移 = 缓冲区大小 + EBP大小(4字节)
Payload偏移 = 返回地址偏移 + 4(JMP ESP地址大小)

1.2.4 防御视角:如何阻止这种攻击

防御技术 如何阻止JMP ESP攻击 效果
ASLR 随机化系统DLL加载地址 JMP ESP地址难以预测
DEP/NX 标记栈为不可执行 即使跳转到Payload也无法执行
栈Canary 检测返回地址是否被修改 在ret执行前就发现攻击
CFG 控制流保护,限制间接跳转 阻止跳转到非常用地址

1.3 总结核心要点

  1. 间接跳转原理 :不直接跳转到Payload,而是通过固定指令中转

  2. ESP的关键作用 :自动指向返回地址之后,提供动态跳转目标

  3. 地址稳定性:JMP ESP指令在系统DLL中,地址相对固定

  4. 攻击链完整性:每个环节必须精确计算,环环相扣

最终答案:

因为JMP ESP指令是固定的中转站 ,而ESP寄存器是智能的向导,它总是在正确的时间指向正确的位置。攻击者利用这个系统特性,让不可预测的栈地址问题通过可预测的系统指令解决,从而可靠地执行Payload。

📊 不同类型攻击的布局对比

攻击类型 内存布局 适用场景
直接跳转 [填充][shellcode地址][shellcode] 知道shellcode确切地址(概率极低)
JMP ESP [填充][JMP ESP地址][NOP][shellcode] 栈地址随机,但系统库地址固定(本例)
寄存器跳转 [填充][JMP EAX地址][shellcode] EAX指向shellcode

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

每一份支持,都是我持续输出的光。

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