🔐 探讨如何利用和操纵程序中的缓冲区溢出漏洞的技术
作者:Sec-Labs | 发布时间:
项目地址
https://github.com/minsooerickim/BufferOverflowAttack
BufferOverflowAttack项目简介
相关技术点
- 缓冲区溢出漏洞
- 反汇编分析
- GDB调试
- 栈操作
- 汇编语言
- ROP
项目用途
该项目旨在通过利用缓冲区溢出漏洞,实现对特定函数参数和返回地址的控制,从而实现对程序的攻击和控制。
具体来说,该项目分为三个部分:
- Part 1:通过覆盖返回地址,实现对程序流的控制,进而跳转到指定函数。
- Part 2:在Part 1的基础上,进一步利用缓冲区溢出漏洞,实现对函数参数的控制。
- Part 3:在Part 2的基础上,通过指定参数,实现调用指定函数,并完成特定操作。
该项目的用途包括但不限于:
- 学习理解缓冲区溢出漏洞的原理和攻击方式。
- 掌握反汇编分析和GDB调试技能。
- 掌握栈操作和汇编语言的知识。
- 熟悉ROP(Return-Oriented Programming)的基本思想和实现方式。
注:本项目仅用于技术学习和研究,切勿用于非法用途。
缓冲区溢出攻击
使用广泛的缓冲区溢出攻击的项目! :)
项目概要
第一部分
在第一部分中,我专注于利用test函数中的缓冲区溢出漏洞。通过仔细检查代码,我确定漏洞来自于strcpy(test, input)行。这一行将用户输入复制到缓冲区中,但没有进行适当的边界检查,导致可能的缓冲区溢出。
为了利用这个漏洞,我反汇编了main函数以了解其结构并确定返回地址的位置。通过分析汇编代码,我发现main函数在地址0x08048e24处调用test函数。下一行,地址为0x08048f68,是我们想要修改的返回地址。
为了计算test函数中的缓冲区和堆栈上的返回地址之间的距离,我使用了GDB。我在test函数开始处设置了断点,在运行带有示例输入的程序后,打印了$ebp寄存器的值(0xffffd668)和test缓冲区的地址(0xffffd64f)。通过将缓冓区地址从$ebp中减去并加上4(为了考虑保存的$ebp值),我确定缓冲区和返回地址之间的距离为29个字节。
利用这些信息,我制作了一个有效载荷,形式为b"A" * 29 + b"\x72\x8e\x04\x08",其中“A”重复29次以填充缓冲区,接下来的4个字节用于将返回地址覆盖为所需的地址0x8048e72(log_result()的位置)。执行有效载荷成功地覆盖了返回地址,使程序的流程转向所需的函数。
第一部分奖励
在第一部分奖励中,我遇到了一个分段错误问题,这是由于log_result函数的返回地址指向任意且不可访问的地址引起的。为了解决这个问题,我修改了漏洞利用程序,以确保log_result函数的返回地址指向有效地址。
通过分析汇编代码和使用GDB,我确定了main函数的结尾地址,这是修改后的返回地址的合适位置。我更新了漏洞利用有效载荷,以包括所需的返回地址,并将其执行为./try_me $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 29 + b"\x72\x8e\x04\x08" + b"\x5a\x91\x04\x08")')。
使用这个修改后的漏洞利用程序,程序不再因分段错误而崩溃,漏洞利用成功执行。
第二部分
在第二部分中,我继续利用漏洞,这次专注于操作函数参数。通过分析汇编代码并理解代码中的条件语句,我确定程序将第一个参数的值与特定值(0xefbeadde)进行比较。为了利用这一点,我需要控制传递给函数的第一个参数。
为了达到这个目的,我在有效载荷中添加了额外的b"AAAA",以确保正确的对齐,并到达堆栈上第一个参数的位置。通过用所需值(0xefbeadde)覆盖第一个参数,我可以通过代码中的条件检查。
我还使用GDB的info address命令找到了log_result_advanced函数的内存地址(0x8048ea0)。有了这个信息,我制作了一个漏洞利用有效载荷:run $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 29 + b"\xa0\x8e\x04\x08" + b"AAAA" + b"\xde\xad\xbe\xef")')。这个有效载荷将返回地址覆盖为log_result_advanced的地址,确保正确的对齐,并修改第一个参数为所需值。
执行有效载荷成功触发了漏洞利用,允许我编写uid_1023_crack_advanced文件。
第三部分
在第三部分中,我的目标是在操作参数的同时触发open(char *filename, flags)函数。为了达到这个目的,我利用缓冲区溢出漏洞并仔细制作有效载荷。
与以前的漏洞利用一样,我用“A”重复29次来填充缓冲区,使其达到精确的位置,其中进一步的字节将覆盖函数的返回地址。但是,我没有将返回地址覆盖为随机数据,而是将其设置为open函数的地址(0x806cef0)。
操作参数需要仔细考虑。我使用将文件名指针推入堆栈的技术,然后推入标志选项。为了确保正确的对齐,我在有效载荷中添加了b"BBBB"和b"\x4c\xca\xff\xff"。
这个漏洞利用的一个挑战是找到内存中uid_1023_crack_super字符串的位置。虽然我最初使用GDB本地标识字符串的位置,但在服务器环境中,我不得不采用逐步添加或减少各种偏移量的蛮力方法,直到找到正确的位置(0xffffca4c)。
最终的有效载荷采取以下形式:./try_me $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 29 + b"\xf0\xce\x06\x08" + b"BBBB" + b"\x4c\xca\xff\xff" + b"\x40\x04" + b"\x90\x90" + b"uid_1023_crack_super" + b"\x00")')。这个有效载荷成功地覆盖了返回地址,操作了参数,并在/home/admin/目录中创建了uid_1023_crack_super文件。
虽然使用ROP链可能会实现类似的结果,但选择缓冲区溢出方法在这种特定情况下更简单、更适合。