这篇文章感觉很难一蹴而就,因为自己还是一个刚刚入门的新手。

栈溢出,就是针对栈空间的溢出,覆盖后面的内存区域,比如:

stack.c

代码:
#include "stdio.h"
int __cdecl main(int __argc,char** __argv, char** __environ){
  
  char buff[8];
  strcpy(buff, __argv[1]);
  
  
  return 0;
} 
汇编形式为
代码:
push    ebp
mov    ebp, esp
sub    esp, 8


mov    eax, dword ptr [ebp+c]  ;__argv
mov    ecx, dword ptr [eax+4]  ;__argv[1]
push    ecx

lea    edx, dword ptr [ebp-8]  ;buff
push    edx

call  [strcpy]
add    esp, 8

xor    eax, eax
mov    esp, ebp
pop    ebp
retn
我们分析eip执行到 call [strcpy] 这句时 栈中的状态吧。

SP<---- buff(8) --- ebp(4) --- mainret(4) --- p1(4) --- p2(4) ---- p3(4) -----SS

假如我们以命令: stack.exe abcd1234来启动进程的话
执行strcpy,将会把abcd1234 复制到 buff 中, 正好8个byte,但是如果我们多输入一个字符呢,比如输入 stack.exe abcd12345  这个时候,abcd1234将填充buff的8个字节,而后面的ascii字符'5'将填充到栈帧ebp中。

如果我们想通过这种溢出机制,修改mainret,那么我们就要越过栈帧ebp,或者我们还可以通过溢出来修改p1,p2,p3等等父函数的参数哦,或者父父函数的内部变量等等,但这样要就要越过栈帧和返回地址mainret了。