Analyzing BufferOverflow with GDB
先决条件: GDB(逐步介绍)
BufferOverflow 经常发生在定义变量内的内容被复制到另一个变量而没有进行绑定检查或考虑缓冲区大小时。让我们借助每个 Linux 系统内置的 GNU 调试器 (GDB) 来分析缓冲区溢出。
本练习的目的是熟悉调试代码并了解缓冲区溢出是如何工作的。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv)
{
volatile int cantoverflowme;
char buffer[64];
cantoverflowme = 0;
gets(buffer);
if (cantoverflowme != 0) {
printf("You OVERFLOW'ed Me
");
}
else {
printf("Can't Overflow Me
");
}
}
- 第 1 步
让我们用以下标志编译这段代码:
gcc overflow.c -o overflow -fno-stack-protector -z execstack -no-pie
上面的代码将创建一个禁用各种堆栈保护的编译二进制文件
-z execstack : Disables Executable Stack
-fno-stack-protector : Disables Stack Canaries
-no-pie : Disables Position Independent Executables - 第 2 步
现在堆栈保护已禁用,我们可以通过键入将代码加载到 GDB 中
gdb ./overflow
- 第 3 步
打开代码后,我们可以通过键入来查看二进制文件中的函数
info functions
我们可以看到正在使用的 gets 调用本质上是易受攻击的,因为它不进行任何绑定检查。
- 第 4 步
让我们输入
disas main
并拆解主函数
- 第 5 步
让我们输入一个断点
b * main+39
这样我们就可以在程序遇到断点时分析栈的内容了。
- 第 6 步
类型
r
运行代码并输入我们已经从上面的代码中知道的任意数量的 A。让我们输入 63 个 A 和 78 个 A,看看结果的变化。
- 第 7 步
离开 GDB 后,您可以使用 python 代码通过键入来打印 A。
python -c "print 'A' * 63"
- 第 8 步
现在我们有 63 个 A,让我们运行代码并在它要求我们输入时粘贴它。
让我们再次尝试整个过程,这次让我们输入任意数量的 A,比如 78。
一个很酷的方法可以是
python -c "print 'A' * 78" | ./overflow
正如我们所见,一旦发生溢出,它就会改变变量,因为堆栈上的内存泄漏并改变了变量的值
- 第 9 步
让我们检查它覆盖的堆栈,所以我们必须设置一个断点
main+39
然后输入
r
然后我们可以输入
x/20s $rsp
x : eXamine
20s : 20 values in string
$rsp : for register RSP (Stack Pointer)因此我们可以看到 78 个 A 是如何写入堆栈并溢出内存的。
注:本文由VeryToolz翻译自 Analyzing BufferOverflow with GDB ,非经特殊声明,文中代码和图片版权归原作者 Coding_Karma所有,本译文的传播和使用请遵循“署名-相同方式共享 4.0 国际 (CC BY-SA 4.0)”协议。