Linux x64 下的万能 Gadget
字数 1208 2025-08-05 08:20:14

Linux x64 下的万能 Gadget 教学文档

一、通用 Gadget 概述

在 Linux x64 环境下进行 ROP (Return-Oriented Programming) 攻击时,__libc_csu_init() 函数提供了一个极其强大的通用 Gadget。这个 Gadget 存在于几乎所有调用了 libc.so 的 x64 程序中,可以用于控制多个寄存器和函数参数。

关键特性:

  • 可以控制最多三个函数参数 (rdi/rsi/rdx)
  • 可以通过函数指针 (通常是 GOT 表项) 调用目标函数
  • 支持循环调用 (通过设置 rbp=rbx+1)
  • 需要至少 56 字节栈空间 (加上返回地址共 64 字节)

二、Gadget 结构分析

主要执行流程:

  1. 0x40061A 开始执行,布置 rbx/rbp/r12/r13/r14/r15 六个寄存器
  2. 返回到 0x400600,继续布置 rdx/rsi/rdi
  3. 通过 call qword ptr[r12+rbx*8] 执行目标函数

栈空间布局:

+------------------+
| 返回地址 (0x40061A) |
+------------------+
| rbx 值           |
+------------------+
| rbp 值           |
+------------------+
| r12 值           |
+------------------+
| r13 值           |
+------------------+
| r14 值           |
+------------------+
| r15 值           |
+------------------+
| 返回地址 (0x400600) |
+------------------+

三、隐藏 Gadget 发现

1. pop rdi; ret Gadget

在地址 0x400622 上的 pop r15; ret 指令 (0x41 0x5F 0xC3) 中,后两个字节 (0x5F 0xC3) 组成了 pop rdi; ret 指令。

用途:

  • 实现单参数函数调用
  • 仅需 24 字节栈空间

栈布局:

+------------------+
| 返回地址 (0x400623) |  // pop rdi; ret 地址
+------------------+
| 参数1 (rdi)      |
+------------------+
| 目标函数地址      |
+------------------+

2. pop rsi; ...; ret Gadget

在地址 0x400620 上的 pop r14 两字节指令 (0x41 0x5E) 中,后一个字节 (0x5E) 是 pop rsi 指令。

结合 0x400623pop rdi; ret,可以实现双参数函数调用。

栈布局:

+------------------+
| 返回地址 (0x400623) |  // pop rdi; ret
+------------------+
| 参数1 (rdi)      |
+------------------+
| 返回地址 (0x400620) |  // pop rsi; ...
+------------------+
| 参数2 (rsi)      |
+------------------+
| 目标函数地址      |
+------------------+

四、实际应用场景

1. 泄漏 libc 函数地址

典型的两步攻击:

  1. 使用 puts(puts@got) 泄漏 libc 函数地址
  2. 计算 system 和 "/bin/sh" 地址
  3. 执行 system("/bin/sh")

2. 单参数函数调用

使用 pop rdi; ret Gadget 可以高效完成:

  • puts(puts@got) 泄漏地址
  • system("/bin/sh") 获取 shell

3. 多参数函数调用

使用完整 Gadget 可以调用需要多个参数的函数

五、总结

  1. __libc_csu_init() 是 Linux x64 下极其强大的通用 Gadget
  2. 包含 pop rdipop rsipop rdxret 等指令片段
  3. 可以组合实现单参数、双参数、三参数函数调用
  4. 最小仅需 24 字节栈空间即可完成基本攻击
  5. 是 Linux x64 ROP 攻击的核心技术之一

六、参考实现

# 示例:使用 pop rdi; ret 调用 puts(puts@got)
rop_chain = [
    pop_rdi_ret,    # 0x400623
    puts_got,       # 参数1: puts@got
    puts_plt,       # 调用 puts
    main_addr       # 返回地址,准备第二阶段
]

# 示例:使用完整 Gadget 调用 execve
rop_chain = [
    csu_init_addr1, # 0x40061A
    0,              # rbx
    1,              # rbp (rbx+1)
    func_ptr,       # r12: 函数指针
    arg1,           # r13 -> rdi
    arg2,           # r14 -> rsi
    arg3,           # r15 -> rdx
    csu_init_addr2, # 0x400600
    0,              # 填充
    0,              # 填充
    0,              # 填充
    0,              # 填充
    0,              # 填充
    0,              # 填充
    0,              # 填充
]
Linux x64 下的万能 Gadget 教学文档 一、通用 Gadget 概述 在 Linux x64 环境下进行 ROP (Return-Oriented Programming) 攻击时, __libc_csu_init() 函数提供了一个极其强大的通用 Gadget。这个 Gadget 存在于几乎所有调用了 libc.so 的 x64 程序中,可以用于控制多个寄存器和函数参数。 关键特性: 可以控制最多三个函数参数 (rdi/rsi/rdx) 可以通过函数指针 (通常是 GOT 表项) 调用目标函数 支持循环调用 (通过设置 rbp=rbx+1) 需要至少 56 字节栈空间 (加上返回地址共 64 字节) 二、Gadget 结构分析 主要执行流程: 从 0x40061A 开始执行,布置 rbx/rbp/r12/r13/r14/r15 六个寄存器 返回到 0x400600 ,继续布置 rdx/rsi/rdi 通过 call qword ptr[r12+rbx*8] 执行目标函数 栈空间布局: 三、隐藏 Gadget 发现 1. pop rdi; ret Gadget 在地址 0x400622 上的 pop r15; ret 指令 ( 0x41 0x5F 0xC3 ) 中,后两个字节 ( 0x5F 0xC3 ) 组成了 pop rdi; ret 指令。 用途: 实现单参数函数调用 仅需 24 字节栈空间 栈布局: 2. pop rsi; ...; ret Gadget 在地址 0x400620 上的 pop r14 两字节指令 ( 0x41 0x5E ) 中,后一个字节 ( 0x5E ) 是 pop rsi 指令。 结合 0x400623 的 pop rdi; ret ,可以实现双参数函数调用。 栈布局: 四、实际应用场景 1. 泄漏 libc 函数地址 典型的两步攻击: 使用 puts(puts@got) 泄漏 libc 函数地址 计算 system 和 "/bin/sh" 地址 执行 system("/bin/sh") 2. 单参数函数调用 使用 pop rdi; ret Gadget 可以高效完成: puts(puts@got) 泄漏地址 system("/bin/sh") 获取 shell 3. 多参数函数调用 使用完整 Gadget 可以调用需要多个参数的函数 五、总结 __libc_csu_init() 是 Linux x64 下极其强大的通用 Gadget 包含 pop rdi 、 pop rsi 、 pop rdx 、 ret 等指令片段 可以组合实现单参数、双参数、三参数函数调用 最小仅需 24 字节栈空间即可完成基本攻击 是 Linux x64 ROP 攻击的核心技术之一 六、参考实现