栈攻击利用之ret2系列(二)
字数 1385 2025-08-23 18:31:17

栈攻击利用之ret2系列(二) 高级技巧详解

1. ret2csu技术

1.1 技术背景

当程序中没有直接的pop rdx; ret gadget时,无法直接控制第三个参数寄存器,导致难以调用readwriteexecve等三参数函数。

1.2 利用条件

  • 程序存在栈溢出漏洞
  • 需要调用参数较多的函数(如write/read/execve等)
  • 缺少直接控制rdx寄存器的gadget

1.3 技术原理

利用__libc_csu_init函数中的两段关键汇编代码:

第一段(寄存器赋值):

.text:000000000040126A 5B pop rbx
.text:000000000040126B 5D pop rbp
.text:000000000040126C 41 5C pop r12
.text:000000000040126E 41 5D pop r13
.text:0000000000401270 41 5E pop r14
.text:0000000000401272 41 5F pop r15
.text:0000000000401274 C3 retn

第二段(函数调用):

.text:0000000000401250 4C 89 F2 mov rdx, r14
.text:0000000000401253 4C 89 EE mov rsi, r13
.text:0000000000401256 44 89 E7 mov edi, r12d
.text:0000000000401259 41 FF 14 DF call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]

1.4 利用方法

构造payload函数:

def csu(rbx, rbp, r12, r13, r14, r15, last):
    payload = b""
    payload += p64(csu_end_addr)  # pop rbx,rbp,r12,r13,r14,r15
    payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
    payload += p64(csu_front_addr)  # call
    payload += b'\x00' * 0x38  # padding
    payload += p64(last)  # return address
    return payload

1.5 参数说明

  • rbx应设为0
  • rbp应设为1(避免跳转)
  • r15为要调用的函数got表地址
  • r12对应edi(第一个参数)
  • r13对应rsi(第二个参数)
  • r14对应rdx(第三个参数)

2. Stack Pivoting(栈迁移)

2.1 技术背景

当溢出空间不足时,通过改变rsp/rbp寄存器将栈迁移到可控内存区域(如.bss段)。

2.2 关键指令

leave; ret指令等同于:

mov esp, ebp; 
pop ebp; 
ret == pop eip

2.3 利用步骤

  1. 第一次迁移

    • 覆盖返回地址为leave; ret gadget
    • 将ebp修改为.bss段地址
  2. 第二次迁移

    • 再次触发leave; ret
    • 将栈完全迁移到.bss段
  3. 第三次利用

    • 在新栈上构造ROP链

2.4 示例代码

# 第一次迁移
payload1 = b'a'*0x30 + p64(bss) + p64(read)

# 第二次迁移
payload2 = b'a'*0x30 + p64(bss + 0x30) + p64(read)

# 第三次利用
payload3 = p64(bss + 0x40) + p64(rdi) + p64(puts_got) + p64(puts_addr) + p64(main)

3. SROP技术

3.1 技术原理

利用sigreturn系统调用恢复寄存器状态的特性构造攻击。

3.2 关键点

  • 需要构造伪造的sigcontext结构体
  • 通过syscall; ret gadget触发
  • 可以一次性设置所有寄存器

4. ret2dlresolve技术

4.1 技术背景

利用动态链接的延迟绑定机制,劫持_dl_runtime_resolve函数的解析过程。

4.2 利用条件

  • 程序无输出函数
  • 未开启FULL RELRO保护

4.3 攻击步骤

  1. 伪造Elf32_Rel/Elf64_Rel结构
  2. 伪造Elf32_Sym/Elf64_Sym结构
  3. 伪造函数名字符串
  4. 劫持_dl_runtime_resolve的解析过程

5. 防御措施

  1. 栈保护

    • 启用栈保护(-fstack-protector)
    • 使用栈随机化(ASLR)
  2. 代码保护

    • 启用FULL RELRO
    • 禁用执行位(NX)
  3. 运行时检测

    • 使用seccomp限制系统调用
    • 实现canary检测

6. 实用工具

  1. ROPgadget

    ROPgadget --binary vuln
    
  2. one_gadget

    one_gadget libc.so.6
    
  3. pwntools

    from pwn import *
    

7. 总结

技术 适用场景 关键点
ret2csu 缺少参数控制gadget 利用__libc_csu_init控制多参数
Stack Pivoting 溢出空间不足 通过leave;ret迁移栈
SROP 需要全面控制寄存器 伪造sigcontext结构
ret2dlresolve 无输出函数 劫持动态链接解析过程

掌握这些高级ret2技术可以应对更复杂的漏洞利用场景,但实际应用中需要根据目标环境灵活组合使用。

栈攻击利用之ret2系列(二) 高级技巧详解 1. ret2csu技术 1.1 技术背景 当程序中没有直接的 pop rdx; ret gadget时,无法直接控制第三个参数寄存器,导致难以调用 read 、 write 、 execve 等三参数函数。 1.2 利用条件 程序存在栈溢出漏洞 需要调用参数较多的函数(如write/read/execve等) 缺少直接控制rdx寄存器的gadget 1.3 技术原理 利用 __libc_csu_init 函数中的两段关键汇编代码: 第一段(寄存器赋值): 第二段(函数调用): 1.4 利用方法 构造payload函数: 1.5 参数说明 rbx 应设为0 rbp 应设为1(避免跳转) r15 为要调用的函数got表地址 r12 对应edi(第一个参数) r13 对应rsi(第二个参数) r14 对应rdx(第三个参数) 2. Stack Pivoting(栈迁移) 2.1 技术背景 当溢出空间不足时,通过改变rsp/rbp寄存器将栈迁移到可控内存区域(如.bss段)。 2.2 关键指令 leave; ret 指令等同于: 2.3 利用步骤 第一次迁移 : 覆盖返回地址为 leave; ret gadget 将ebp修改为.bss段地址 第二次迁移 : 再次触发 leave; ret 将栈完全迁移到.bss段 第三次利用 : 在新栈上构造ROP链 2.4 示例代码 3. SROP技术 3.1 技术原理 利用 sigreturn 系统调用恢复寄存器状态的特性构造攻击。 3.2 关键点 需要构造伪造的sigcontext结构体 通过 syscall; ret gadget触发 可以一次性设置所有寄存器 4. ret2dlresolve技术 4.1 技术背景 利用动态链接的延迟绑定机制,劫持 _dl_runtime_resolve 函数的解析过程。 4.2 利用条件 程序无输出函数 未开启FULL RELRO保护 4.3 攻击步骤 伪造Elf32_ Rel/Elf64_ Rel结构 伪造Elf32_ Sym/Elf64_ Sym结构 伪造函数名字符串 劫持 _dl_runtime_resolve 的解析过程 5. 防御措施 栈保护 : 启用栈保护(-fstack-protector) 使用栈随机化(ASLR) 代码保护 : 启用FULL RELRO 禁用执行位(NX) 运行时检测 : 使用seccomp限制系统调用 实现canary检测 6. 实用工具 ROPgadget : one_ gadget : pwntools : 7. 总结 | 技术 | 适用场景 | 关键点 | |------|---------|--------| | ret2csu | 缺少参数控制gadget | 利用__ libc_ csu_ init控制多参数 | | Stack Pivoting | 溢出空间不足 | 通过leave;ret迁移栈 | | SROP | 需要全面控制寄存器 | 伪造sigcontext结构 | | ret2dlresolve | 无输出函数 | 劫持动态链接解析过程 | 掌握这些高级ret2技术可以应对更复杂的漏洞利用场景,但实际应用中需要根据目标环境灵活组合使用。