學習堆棧知識,實現一個簡單的棧溢出攻擊。
代碼如下圖,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函數,從而實現棧溢出攻擊。
