【漏洞复现】软件漏洞——栈溢出漏洞复现及其原理详解 一文解明什么是栈溢出漏洞

造成软件漏洞原因:

本质原因是因为人类目前还没办法在原点上区分数据与代码,说白了就是目前人们还没理解编写安全代码的真正方法。

如何预防?

通过修改自身代码、公共库函数的安全性降低漏洞出现频率,并且通过操作系统干预,使得漏洞攻击变得难以实现。

软件漏洞常见名词

vulnerability:漏洞、计算机安全隐患。Exploit[ik 'splbrt] :漏洞利用。
Shellcode:壳代码
Payload:有效荷载,payload是 shellcode 的一部分, shellcode_的执行往往就是为了给 payload代码开辟道路,说白了就是真正干坏事的代码。

栈溢出漏洞

复现前准备

栈溢出漏洞是一个很经典且非常危险的漏洞,我们来写一个简单的代码复现并了解一下它的原理。
在我们项目属性中将选项设置如下。使用Release版本x86进行调试。

在这里插入图片描述
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<iostream>

int checkPassword(const char* password)
{
	int result = 1;
	char buff[7]{};
	result = strcmp(password, "51hook");
	strcpy(buff, password);
	return result;
}

int main()
{
	int flag = 0;
	char password[0x500];
	while (1)
	{
		printf("请输入密码\n");
		int result = scanf("%s", password);
		flag = checkPassword(password);
		if (flag)
		{
			MessageBoxA(0, "密码错误!", "提示", MB_OK);
		}
		else
		{
			MessageBoxA(0, "密码正确!", "提示", MB_OK);
			break;
		}
	}
	return 0;
}

可以看到我们正常执行输入错误密码会弹窗错误,接下来我们要通过栈溢出漏洞来绕过密码检测,让他提示正确。
在这里插入图片描述

我们拿出release版的32位exe文件进行调试。
找到我们的main函数位置
在这里插入图片描述
我们在过程中会调用scanf函数,来输入wwwwww
在这里插入图片描述
步进到我们的checkpassword时停止,我们进入函数查看。

前面先提升堆栈并初始化栈空间

在这里插入图片描述
然后把输入的和要检测的都压入堆栈。

在这里插入图片描述
到目前为止一切正常
在这里插入图片描述
当我们执行完strcpy函数时我们就能够发现在值钱开辟的堆栈空间中,***我们之前输入的字符串放进去了,放到了我们的buff缓冲区中,***但是这个时候问题就出现了,我们之前定义缓冲区大小为0x500而我们在checkPassword函数中定义时buff缓冲区大小只有7.我们验证的密码51hook加上\0正好为7,但是传进来的password大小要远比这个缓冲区大小要大,我们这时只输入了6个w,也就是并没有超出缓冲区的界限,可以看到我们的buff缓冲区也成功存储了wwwwww,我们再往下看。

在这里插入图片描述

在这里插入图片描述
下一条指令我们将mov eax,[ebp-4]ebp-4存的是什么?从正向代码我们可以知道这是我们的result局部变量,通过将其置1 来判断我们输入的密码输入正确还是错误,通过上面分析我们可以得知password大小远超出buff缓冲区大小,而从上图我们可以得知这 关键的返回值result=0x00000001中重要的01紧紧挨着我们的buff缓冲区,那我们是不是可以通过控制这个关键的01给他改为00,让result=0x00000000从而绕过密码的检测直接达成密码正确的目的呢?我们来试一下

在这里插入图片描述
重新运行我们的exe文件,这回我们在输入时,输入wwwwwwww八个w,因为上文我们知道buff缓冲区大小只有7个,因为对齐才成为8个,在我们输入完后字符串他会看到\0才会停止,我们输入8个w,所以他在原本01的位置就会自动补为0,而我们要修改01为00,的目的也就达到了。

在这里插入图片描述
我们可以看到以前的01部分已经被我们的输入覆盖掉了成了00,让我们把他执行完。01
可以确实的看到虽然我们并没有输入正确的密码,我们也绕过了验证,达到了我们想要的效果,这就是栈溢出漏洞。
在这里插入图片描述

<think>好的,我现在需要解决用户在GDB调试过程中遇到的栈溢出问题。首先,我得理解栈溢出的常见原因。根据用户提供的引用[4],递归调用过深导致无限递归是一个典型原因,比如函数没有正确的终止条件。那可能还有其他原因,比如局部变量过大或者过多的嵌套函数调用。 接下来,我需要考虑如何在GDB中检测栈溢出。用户提到了使用backtrace和info frame命令,这些可以帮助查看调用栈的情况。此外,设置断点可能在问题发生前捕获到异常,比如在递归函数内部设置断点,或者监测栈指针的变化。 然后,关于动态分析工具,用户提到了Valgrind的Memcheck工具,引用[2]中的命令可以检测内存泄漏和栈溢出。不过Valgrind对于栈溢出的检测可能有限,可能需要结合其他工具或方法。 另外,用户提供的引用[5]涉及ELF文件的结构,虽然和栈溢出没有直接关系,但在调试时了解符号表可能有帮助,比如查看函数符号是否正确解析,排除其他潜在问题。 还需要考虑编译器的保护机制,比如GCC的-fstack-protector选项,这可以在编译时加入栈保护,检测溢出。同时,优化栈使用,比如减少局部变量的大小,或者将大数组分配到堆上。 可能用户的问题是由于递归函数没有终止条件,或者局部变量占用了太多栈空间。在调试时,需要复现问题,观察栈的增长情况,检查是否有无限递归或过深的调用链。 总结下来,解决方案应包括原因分析、调试技巧(如GDB命令)、工具使用(Valgrind)、编译器选项和代码优化。同时,用户可能需要修改代码,比如添加终止条件或改用堆内存。</think>### GDB调试中栈溢出问题的解决方案 #### 一、栈溢出原因分析 1. **递归调用失控** - 未设置正确的递归终止条件,导致函数无限递归 - 示例代码(引用[4]): ```c void recursiveFunction() { recursiveFunction(); // 无限递归导致栈溢出 } ``` 2. **大体积局部变量** - 在栈上分配超大数组或结构体(如:`char buffer[10MB]`) 3. **深度嵌套调用** - 函数调用链超过默认栈空间(Linux默认栈大小通常为8MB) #### 二、GDB调试技巧 1. **查看调用栈** ```bash (gdb) backtrace full # 显示完整调用栈及局部变量 (gdb) info frame # 查看当前栈帧详细信息 ``` 2. **设置断点监测** ```bash (gdb) break recursiveFunction # 在可疑函数设置断点 (gdb) watch $esp # 监控栈指针变化(x86架构) ``` 3. **栈空间检测** ```bash (gdb) print (void*)&var # 查看变量地址估算栈使用量 (gdb) info proc mappings # 查看进程内存映射,确认栈区间 ``` #### 三、动态分析工具 1. **Valgrind检测(引用[2])** ```bash valgrind --tool=memcheck --leak-check=full ./program ``` 2. **核心转储分析** ```bash ulimit -c unlimited # 启用核心转储 gdb ./program core # 分析崩溃现场 ``` #### 四、编译器保护机制 ```bash gcc -fstack-protector-all -o program source.c # 启用栈保护 gcc -Wstack-usage=4096 # 警告超过指定栈用量的函数 ``` #### 五、代码优化方案 1. **递归转迭代** ```c // 修改前 void recursive(int n) { if(n == 0) return; recursive(n-1); } // 修改后 void iterative(int n) { while(n > 0) n--; } ``` 2. **堆内存分配** ```c // 修改前 void func() { char buffer[10*1024*1024]; // 栈分配 } // 修改后 void func() { char* buffer = malloc(10*1024*1024); // 堆分配 free(buffer); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

webfker from 0 to 1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值