0x00 序
"Hello,World!"的浪漫可能只有直男才懂!在1就是1、0就是0的非黑即白的元宇宙世界里一定只会有少年的足迹!天真永不消逝,浪漫至死不渝!生命不熄,学习不止!致每一个有梦想却被现实抛弃和质疑的追梦人!
言归正传,最近在学习二进制漏洞的挖掘,今天就拿一个demo做一个return to text的分析。
0x01 文件分析
Demo是一个名为ret2text的文件,在Ubuntu中使用file命令查看文件信息。
- 是一个ELF可执行文件
- 32位
- 小端序
- i386架构
使用checksec查看保护开启情况
- RELRO开启Partial模式
- 未开启金丝雀保护
- 堆栈不可执行
- 未开启内存地址随机化
0x02 静态分析
使用32位IDA打开ELF文件
查看分析伪代码
- 定义字符变量s。
- 调用gets函数获取输入并存到s中。
- 在调用gets函数时并未对输入进行长度的判断,存在可溢出点。
查看汇编代码
- 在调用gets函数之前将参数s的地址赋值给了eax
- 并将s的地址作为gets函数的参数压住栈中
0x03 动态调试
在Ubuntu使用GDB调试文件。
将断点下到main函数,运行文件。
单步调试到调用gets函数时。
- 此时eax的值(参数s的地址)为0xffffd0bc。
使用命令stack查看函数调用栈的情况。
- esp指针的地址为0xffffd0a0
- ebp指针的地址为0xffffd128
- 那么函数返回的地位就是0xffffd12c
- s的位置在0xffffd0bc。
测试输入覆盖
- 可以完成栈数据的覆盖
计算输入点到返回地址的长度
- 0x70的长度可以覆盖到返回地址
测试
- 成功覆盖到返回值地址
- 可再用四个字节即可覆盖返回地址
0x04 查找代码可执行点
在IDA查询是否有system函数可以利用。
- 文件调用了system()函数
- 并在调用时直接执行了/bin/sh命令
查找命令执行的地址
- 找到引用地址0x0804863A
0x05 POC编写
from pwn import *
context.arch = "i386"
p = process("./ret2text")
elf = ELF("./ret2text")
libc = ELF("/lib/i386-linux-gnu/libc-2.27.so")
padding = "a"*0x70
retaddr = 0x0804863A
payload = padding + p32(retaddr)
p.sendlineafter("do you know anything?\n",payload)
p.interactive()
- 该POC脚本为本地利用,pwntools也提供远程利用方式。
- 使用了相对地址,脚本与文件放在同一目录下。
0x06 运行脚本
- 成功执行命令