您的位置:首页 > 其它

浅谈缓冲区溢出检查_security_cookie

2013-12-17 12:00 92 查看
介绍:

当应用程序启动时,程序的cookie(4字节(dword),无符号整型)被计算出来(伪随机数)并保存在

加载模块的.data节中,在函数的开头这个cookie被拷贝到栈中,位于EBP和返回地址的正前方(位于返

回地址和局部变量的中间)。



[buffer][cookie][savedEBP][savedEIP]

在函数的结尾处,程序会把这个cookie和保存在.data节中的cookie进行比较。

如果不相等,就说明进程栈被破坏,进程被终止。



在典型的缓冲区溢出中,栈上的返回地址会被数据所覆盖,但在返回地址被覆盖之前,cookie早已经被

覆盖了,因此在函数的结尾程序会发现cookie已经被破坏,接着应用程序会被结束。

实践:

VC编译器启用Buffer Security Check时,会在有字符串操作的函数处加入_security_cookie,也就是用来检查缓冲区溢出

如下图的配置,默认是打开的:



接下来我们看下,在有字符串等缓冲区操作的函数,编译器会添加什么代码来检查:

首先在函数入口处:

00401050 83ec10          sub     esp,10h
00401053 a100a04100      mov     eax,dword ptr [CSWinMain1!__security_cookie (0041a000)]
00401058 33c4            xor     eax,esp
0040105a 8944240c        mov     dword ptr [esp+0Ch],eax
0040105e 6a0c            push    0Ch
取出__security_cookie, xor esp 放在当前esp+0ch处

在函数返回时有如下代码:

0040109c 8b4c2428        mov     ecx,dword ptr [esp+28h]
004010a0 83c41c          add     esp,1Ch
004010a3 33cc            xor     ecx,esp
004010a5 e862010000      call    CSWinMain1!__security_check_cookie (0040120c)


由于esp在中间操作过,所以这里esp+28h就是之前存放cookie值的,取出来,然后 xor回去;

call    CSWinMain1!__security_check_cookie (0040120c)
在进去看到如下代码:

CSWinMain1!__security_check_cookie:
0040120c 3b0d00a04100    cmp     ecx,dword ptr [CSWinMain1!__security_cookie (0041a000)]
00401212 7502            jne     CSWinMain1!__security_check_cookie+0xa (00401216)
00401214 f3c3            rep ret
00401216 e981150000      jmp     CSWinMain1!__report_gsfailure (0040279c)
这里看到这个ecx值和原始存放的值进行了比较,如果不相等,则跳到__report_gsfailure.

如果要更详细的了解实现,也可以查看相关的源码在:

X:\Program Files\Microsoft Visual Studio 8\VC\crt\src\gs_report.c

X:\Program Files\Microsoft Visual Studio 8\VC\crt\src\gs_cookie.c

那么使用这个的好处大家应该可以看到了,具体我们来看下_security_cookie有或无时crash的 dump;

没用_security_cookie

STACK_TEXT:  
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012ff38 41414141 00414141 005c1b70 005c1bc0 0x41414141
0012ff88 76baed6c 7ffdb000 0012ffd4 772337eb 0x41414141
0012ff94 772337eb 7ffdb000 77bc2d38 00000000 kernel32!BaseThreadInitThunk+0xe
0012ffd4 772337be 00401449 7ffdb000 00000000 ntdll!__RtlUserThreadStart+0x70
0012ffec 00000000 00401449 7ffdb000 00000000 ntdll!_RtlUserThreadStart+0x1b


这个stack已经乱了,其实0x41414141这个地址就是被溢出时的字符串,这么看就比较难定位原因了;

用了_security_cookie

0012fbec 0040287b 00417264 834f4bdb 7cb0b424 kernel32!UnhandledExceptionFilter+0x5f
0012ff20 004010aa 64636261 6766652b 6c6b6a68 CSWinMain1!__report_gsfailure+0xdf [f:\dd\vctools\crt_bld\self_x86\crt\src\gs_report.c @ 313]
0012ff88 76baed6c 7ffd6000 0012ffd4 772337eb CSWinMain1!Test1+0x5a [e:\projects\cswinmain1\cswinmain1.cpp @ 36]
0012ff88 76baed6c 7ffd6000 0012ffd4 772337eb kernel32!BaseThreadInitThunk+0xe
0012ff94 772337eb 7ffd6000 7754c743 00000000 kernel32!BaseThreadInitThunk+0xe
0012ffd4 772337be 00401468 7ffd6000 00000000 ntdll!__RtlUserThreadStart+0x70
0012ffec 00000000 00401468 7ffd6000 00000000 ntdll!_RtlUserThreadStart+0x1b
通过stack,可以看到具体错误的函数,返回地址不会因此而变成未知地址,可以确定错误原因就在那个Test1函数某处字符串操作的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: