前两天,在论坛上看了泉哥的“泉行之路”和笨笨熊的“职场游记”,深受鼓舞,于是决定写下下面这篇鸟文,高手飘过,如有错误,概不负责哦 ,呵呵

   引子:<本文的分析是在debug模式下,呜呜,有人怒了……>
  在vc6.0下,写溢出程序很容易,在.net下由于添加了/GS选项,加入了__security__cookie,溢出就没那么简单了。对_security_cookie我也是最近才研究了一下,才知道:当在函数中buff的长度 <= 4时,编译器是不会在函数中插入cookie进行校验的。于是产生了下面这个天真的想法:
void  foo()
{
  char  buf[4] = {0};    
  strcpy(buf,shellcode);  
}
是不是这样foo函数流程就能被逆转了呢(想法很天真呐,嘿嘿……),于是我就进行尝试了一把,结果挂了,弹出下面这个框框:


  单步调试,才发现编译器加入了函数void __fastcall _RTC_CheckStackVars(void *frame, _RTC_framedesc *v)对函数的局部变量进行校验……呜呼,显然我的想法很傻很天真

    其实微软的编译器是这么检查堆栈变量的:在一个存在局部变量的函数里头,编译器统计函数的局部变量个数num,在栈上分配 192 + num * 2 * sizeof(DWORD) + num*sizeof(DWORD)个字节的栈空间,并将其全部填充为0xCCCCCCCC,当函数结束后,编译器会检测每个局部变量的前4个字节和后四个字节是否为0xCCCCCCCC,如果不是,则说明发生数据覆盖等,跳向错误处理……

  实例演示:
 

代码:
#include <stdio.h>
void foo()
{
  char x[4] = {0};
  char  y[4] = {0};
  x[3] = 'A';
  y[3] = 'A';
  printf("x = %x\n",x[3]);
  printf("x = %x\n",y[3]);
}

void main()
{
  foo();
}
用vs2005编译后,用ida打开,进入foo函数内部:

继续往下走,找到_RTC_CheckStackVars函数:

在进入_RTC_CheckStackVars函数之前我们先分析一下变量v到底是个什么东西……

下面在进入关键函数_RTC_CheckStackVars分析:


  通过对编译器插入的函数_RTC_CheckStackVars的分析,估计大家对编译器的行为又有了一个新的了解。