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

Linux x64 下的万能 Gadget 教学文档

一、概述

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

二、通用Gadget详解

1. __libc_csu_init()的基本结构

__libc_csu_init()函数包含两个关键部分:

  1. 第一部分 (0x40061A):

    • 可以控制六个寄存器: rbx/rbp/r12/r13/r14/r15
    • 通过ret指令跳转到第二部分
  2. 第二部分 (0x400600):

    • 控制rdx/rsi/rdi三个寄存器
    • 通过call qword ptr[r12+rbx*8]执行目标函数

2. 使用方法

要使用这个Gadget,需要按照以下步骤布置栈空间:

  1. 从0x40061A开始执行
  2. 布置六个寄存器的值:
    • rbx
    • rbp (通常设置为rbx+1以实现循环)
    • r12 (函数指针)
    • r13 (rdx的值)
    • r14 (rsi的值)
    • r15 (rdi的值)
  3. 返回地址设置为0x400600
  4. 在0x400600处继续布置:
    • 填充空间 (对应add rsp,8)
    • rbx/rbp/r12/r13/r14/r15的再次设置
    • 目标函数的返回地址

3. 空间需求

一次完整调用需要:

  • 六个寄存器值 (6 QWORDs = 48字节)
  • 一个返回地址 (8字节)
  • 总计56字节栈空间
  • 如果包括初始跳转的ret地址,共需要64字节栈空间

三、隐藏的简化Gadget

1. pop rdi; ret Gadget

在地址0x400623处隐藏了一个pop rdi; ret Gadget:

  • pop r15; ret指令的后两个字节(0x5F 0xC3)组成
  • 可用于单参数函数调用

栈布置 (24字节):

| 返回地址 (0x400623) |
| 参数值             |
| 函数地址           |

2. pop rsi; ...; ret Gadget

在地址0x400620处隐藏了一个pop rsi指令:

  • pop r14指令的后一个字节(0x5E)组成
  • 可与pop rdi; ret组合实现双参数函数调用

栈布置:

| 返回地址 (0x400620) |
| r14值 (无用)        |
| 返回地址 (0x400623) |
| rdi值              |
| rsi值              |
| 函数地址           |

四、实际应用场景

1. 泄漏libc地址

典型的两阶段攻击:

  1. 泄漏阶段:

    • 使用pop rdi; ret调用puts(puts@got)
    • 获取libc函数实际地址
    • 计算system"/bin/sh"的地址
  2. 执行阶段:

    • 使用pop rdi; ret调用system("/bin/sh")

2. 多参数函数调用

对于需要多个参数的函数,可以使用完整Gadget或组合隐藏Gadget:

  • 单参数:pop rdi; ret
  • 双参数:组合pop rsipop rdi; ret
  • 三参数:使用完整Gadget控制rdx/rsi/rdi

五、总结

  1. __libc_csu_init()是Linux x64环境下极其强大的通用Gadget
  2. 完整Gadget可以控制最多三个函数参数(rsi/rdi/rdx)和函数指针
  3. 隐藏的简化Gadget(pop rdi; retpop rsi)可以用于简单场景
  4. 空间需求从24字节(简化Gadget)到64字节(完整Gadget)不等
  5. 适用于各种ROP场景,包括libc地址泄漏和最终shell获取

六、参考实现

# 示例ROP链构造
from pwn import *

# 通用Gadget地址
csu_init_part1 = 0x40061A
csu_init_part2 = 0x400600
pop_rdi_ret = 0x400623
pop_rsi_r15_ret = 0x400620

# 构造单参数ROP链
def single_arg_rop(func_addr, arg):
    return flat([
        pop_rdi_ret,
        arg,
        func_addr
    ])

# 构造双参数ROP链
def double_arg_rop(func_addr, arg1, arg2):
    return flat([
        pop_rsi_r15_ret,
        arg2,
        0,  # 填充r15
        pop_rdi_ret,
        arg1,
        func_addr
    ])

# 构造完整Gadget ROP链
def full_gadget_rop(func_ptr, rdx, rsi, rdi, rbx=0, rbp=1):
    return flat([
        csu_init_part1,
        rbx,
        rbp,
        func_ptr,  # r12
        rdx,       # r13
        rsi,       # r14
        rdi,       # r15
        csu_init_part2,
        0,         # add rsp,8
        0, 0, 0, 0, 0, 0  # 填充
    ])

通过合理利用这些Gadget,可以构建出适应各种场景的ROP攻击链。

Linux x64 下的万能 Gadget 教学文档 一、概述 在Linux x64环境下进行ROP (Return-Oriented Programming)攻击时, __libc_csu_init() 函数提供了一个极其强大的通用Gadget。这个Gadget存在于几乎所有调用了libc.so的x64程序中,可以用于控制多个寄存器和函数参数,实现复杂的ROP链构造。 二、通用Gadget详解 1. __libc_csu_init() 的基本结构 __libc_csu_init() 函数包含两个关键部分: 第一部分 (0x40061A): 可以控制六个寄存器: rbx/rbp/r12/r13/r14/r15 通过 ret 指令跳转到第二部分 第二部分 (0x400600): 控制rdx/rsi/rdi三个寄存器 通过 call qword ptr[r12+rbx*8] 执行目标函数 2. 使用方法 要使用这个Gadget,需要按照以下步骤布置栈空间: 从0x40061A开始执行 布置六个寄存器的值: rbx rbp (通常设置为rbx+1以实现循环) r12 (函数指针) r13 (rdx的值) r14 (rsi的值) r15 (rdi的值) 返回地址设置为0x400600 在0x400600处继续布置: 填充空间 (对应add rsp,8) rbx/rbp/r12/r13/r14/r15的再次设置 目标函数的返回地址 3. 空间需求 一次完整调用需要: 六个寄存器值 (6 QWORDs = 48字节) 一个返回地址 (8字节) 总计56字节栈空间 如果包括初始跳转的ret地址,共需要64字节栈空间 三、隐藏的简化Gadget 1. pop rdi; ret Gadget 在地址0x400623处隐藏了一个 pop rdi; ret Gadget: 由 pop r15; ret 指令的后两个字节(0x5F 0xC3)组成 可用于单参数函数调用 栈布置 (24字节): 2. pop rsi; ...; ret Gadget 在地址0x400620处隐藏了一个 pop rsi 指令: 由 pop r14 指令的后一个字节(0x5E)组成 可与 pop rdi; ret 组合实现双参数函数调用 栈布置 : 四、实际应用场景 1. 泄漏libc地址 典型的两阶段攻击: 泄漏阶段 : 使用 pop rdi; ret 调用 puts(puts@got) 获取libc函数实际地址 计算 system 和 "/bin/sh" 的地址 执行阶段 : 使用 pop rdi; ret 调用 system("/bin/sh") 2. 多参数函数调用 对于需要多个参数的函数,可以使用完整Gadget或组合隐藏Gadget: 单参数: pop rdi; ret 双参数:组合 pop rsi 和 pop rdi; ret 三参数:使用完整Gadget控制rdx/rsi/rdi 五、总结 __libc_csu_init() 是Linux x64环境下极其强大的通用Gadget 完整Gadget可以控制最多三个函数参数(rsi/rdi/rdx)和函数指针 隐藏的简化Gadget( pop rdi; ret 和 pop rsi )可以用于简单场景 空间需求从24字节(简化Gadget)到64字节(完整Gadget)不等 适用于各种ROP场景,包括libc地址泄漏和最终shell获取 六、参考实现 通过合理利用这些Gadget,可以构建出适应各种场景的ROP攻击链。