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()函数包含两个关键部分:
-
第一部分 (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字节):
| 返回地址 (0x400623) |
| 参数值 |
| 函数地址 |
2. pop rsi; ...; ret Gadget
在地址0x400620处隐藏了一个pop rsi指令:
- 由
pop r14指令的后一个字节(0x5E)组成 - 可与
pop rdi; ret组合实现双参数函数调用
栈布置:
| 返回地址 (0x400620) |
| r14值 (无用) |
| 返回地址 (0x400623) |
| rdi值 |
| rsi值 |
| 函数地址 |
四、实际应用场景
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获取
六、参考实现
# 示例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攻击链。