感谢师兄秋刀鱼,感谢你半年前教会了我,然后我又不记得了,你又耐心的教了我一次。
建议一定要把VS2022的优化啥的关掉。 把环境弄成X86的 这样方便看内存地址的长度,更好找
废话不多说。
常用的汇编指令 call Lea push pop mov 这些请先去自行了解再来看这个文章。
内存被分了好几个区域,比如,堆栈,常量区,代码区啥的。感兴趣的自己看看书哈。
这里我们来看看 栈区: 由编译器自动分配释放,存放函数的参数值,局部变量的值等。
我用这个求学生成绩中和的代码说明。
#include <iostream>
using namespace std;
int hake() {
cout << " 笨蛋" << endl;
return 0;
}
int sum() {
int student[5]{};
int SUM{};
int i{};
do {
scanf_s("%d", &student[i]);
SUM += student[i];
} while (student[i++]);
return SUM;
}
int main() {
//cout << hake<<endl;
printf("%d\r\n", hake);
cout << sum();// 把断点下在这里 ,这样就可以看到 call 是怎么调用这个函数的。
}
所以我代码里面写的 i students SUM 都是属于栈区的。 看看程序函数是怎么入栈的吧
1. 先用这个 call 把 call的下一条指令的内存地址(2323858)入栈, 这个就是这个函数最后返回的地址。 在修改ip寄存器的地址为(231078)。
2. 接着单步调试看看,把 student入栈并初始化,接着 把SUM 入栈 初始化,入栈 i 并初始化。
3. 在内存里面可以看到 SUM 和 i 和 student 的内存地址之间还间隔了一个系统多分配的空间。
4. 再student 分配5个空间初始化为0后,还有12个字节的空间 这个是系统为了防止栈溢出的多分配的内存。这多出来的12个字节后面 是58 28 23 00就是我在第一步强调的返回地址。
5.我们在输入的8个数据 后 就是在第9个内存单元也就是返回地址上输入 hack的内存地址。 这样就实现了最最最经典的栈溢出攻击修改返回地址。
6. 最后输入0 让sum() 执行return 就返回到了hack函数去了。
我的电脑和你们不一样,主要学这个方法, 总的来说就是 找到 返回地址 修改 它最后出栈会调用这个 返回地址。
我之前看了好几个版本的,我自己总结下再写出来,如果有什么没看懂的地方我会积极回复的!!给个三连!!
这个例子可以更好的理解系统中的栈区到底是怎么个回事!请大家思考下 如果吧代码写成这样 还能实现栈溢出攻击吗?
int sum() {
int SUM{};
int i{};int student[5]{};
do {
scanf_s("%d", &student[i]);
SUM += student[i];
} while (student[i++]);
return SUM;
}
谢谢查看。