此篇文章是对ret2text的学习初步总结。
目标利用栈溢出执行危险程序获取shell
解体思路:
一、checksec查看二进制文件属性
打开linux终端
- Arch: 64位小端序架构(amd64)即后续使用IDA64进行反汇编。
- RELRO: 部分 RELRO(Relocation Read-Only),这意味着某些部分的内存是只读的,但并非所有部分都是如此。这通常意味着GOT表(Global Offset Table)是可写的,可能存在GOT覆写攻击的风险。
- Stack: 没有栈保护(No canary found),这意味着栈上没有使用canary来防止缓冲区溢出攻击。这是一个安全风险点。(攻击关键点,可以通过栈溢出控制返回)
- NX: NX启用(Non-Executable Stack),这意味着栈上的数据不可执行,有助于防止ROP(Return Oriented Programming)攻击。
- PIE: 没有启用PIE(Position Independent Executable),这意味着程序加载时的基地址是固定的(0x400000),而不是随机的。这使得一些基于地址随机化的防护机制失效,可能会增加漏洞利用的成功率。
二、将文件拖入IDA分析
F5查看底代码寻找溢出漏洞
发现gets()危险,函数char s[128];
定义了一个大小为128字节的字符数组 s,
在这个上下文环境中'char s[128]被分配在了栈上并且占据了连续的一块内存区域
1. gets()
函数的缺陷
gets()
函数从标准输入读取一行字符串,并将其存储在指定的缓冲区中。然而,gets()
函数有一个致命的缺陷:它不会检查输入的字符串长度是否超过了目标缓冲区的大小。这意味着如果用户输入的字符串长度超过128字节(即数组 s
的大小),gets()
会继续将数据写入缓冲区之外的内存区域,从而导致缓冲区溢出(Buffer Overflow)。
2. 缓冲区溢出的危害
缓冲区溢出是一种常见的安全漏洞,可能导致以下几种严重后果:
- 程序崩溃:当写入的数据覆盖了栈帧中的其他重要数据时,可能会导致程序异常终止或崩溃。
- 任意代码执行:攻击者可以精心构造输入数据,使得溢出的数据恰好覆盖返回地址或其他控制流相关的信息,从而劫持程序的执行流程,执行任意恶意代码。这种攻击方式被称为“栈溢出攻击”或“ROP(Return-Oriented Programming)攻击”。
- 信息泄露:溢出的数据可能覆盖敏感信息(如密码、密钥等),导致这些信息被泄露给攻击者。
发现可利用后门函数,接下来找出该函数地址
打开IDA View-A右键开启文本模式
找到返回后门函数地址为40063B(/bin/sh)且下方有call _system
三、集齐攻击所需要素开始编写exp进行本地攻击和
编写exp时注意返回地址为16进制在IDA中找到的函数地址为二进制,故写exp时需在前面加上0x
from pwn import *
# 启动进程并获取控制权
io = process('./baby_ret2')
# 定义 system() 函数的地址(假设已知)
system_addr = 0x40063B
# 构造 payload,用于触发缓冲区溢出漏洞
payload = b'a' * 128 + b'b' * 8 + p64(system_addr)
# 发送 payload 到目标进程
io.sendline(payload)
# 进入交互模式以便观察结果或进一步操作
io.interactive()
-
b'a' * 128
: 这部分生成了一个由128个字节 'a' 组成的字符串。这些字节将填充到目标缓冲区s
中,确保填满整个缓冲区。由于s
的大小是128字节,因此这部分数据正好覆盖了整个缓冲区。 -
b'b' * 8
: 这部分生成了一个由8个字节 'b' 组成的字符串。这些字节将覆盖缓冲区s
之后的内存区域。具体来说,它们会覆盖栈帧中的某些重要数据结构,例如返回地址或保存的基址指针(rbp)等。通过精心控制这8个字节的值,攻击者可以操纵程序的执行流程。 -
p64(system_addr)
: 这部分将系统调用函数system()
的地址转换为64位二进制格式,并将其附加到 payload 的末尾。这个地址将被写入到栈帧中被覆盖的部分(通常是返回地址的位置),从而在函数返回时跳转到system()
函数执行恶意代码。这里的p64()
是一个常用的工具函数,用于将整数转换为64位的二进制表示形式
写好exp后打开终端运行输入:python3 exp.py(使用python3运行exp)
本地已打通后使用ls可看到文件名(baby-ret2)获取到shell,开始打远程打开靶机
修改exp将process改为remote并将括号内的内容改为端口号加ip
改好后打开终端ctrl+c打断上一步进程再次运行exp,cat flag即可获得flag