push ebp
mov ebp,esp
push FFFFFFFF
push sdk.FAB99E9 ; New Exception handler
mov eax,dword ptr fs:[0] ; Old Exception handler
push eax
sub esp,14 ; Allocate 5 DWORDs
push ebx
push esi
push edi
mov eax,dword ptr ds:[FAC635C] ; The GS cookie (.data section)
xor eax,ebp
push eax ; The GS Cookie
lea eax,dword ptr ss:[ebp-C]
mov dword ptr fs:[0],eax ; Set new Exception Handler
mov edi,ecx ; Address of a vector passed as arg1
mov dword ptr ss:[ebp-20],edi ; local variable
mov dword ptr ss:[ebp-1C],0 ; local variable
mov dword ptr ds:[edi],0 ; zero the vector
mov dword ptr ds:[edi+4],0
mov dword ptr ds:[edi+8],0
mov dword ptr ss:[ebp-4],0 ; sets the 0xFFFFFFFF above to 0x0
mov dword ptr ss:[ebp-1C],1
mov byte ptr ss:[ebp-D],0
该函数注释为“新异常处理程序”,确实包含Cookie检查。但是我从未涉足其中。
谁能解释一下它的工作原理以及在C ++中的样子吗?或者,更具体地满足我的需求,这是原始代码中的try / catch块还是由编译器添加的?
#1 楼
该函数注释为“新异常处理程序”,它包含Cookie检查。但是我从来都无法涉足它。 。
至于Epilog中缺少cookie的检查,显然您的功能不是使用普通的旧
GS
cookie(通过简单比较返回地址覆盖保护),而是仅使用改进的EH+GS
cookie(局部变量+ EH)数据+返回地址保护以及额外的XOR检查)。 注释的函数序言(注释指的是框架中的最终偏移量):
push ebp ; [EBP+0] save old EBP
mov ebp, esp ; set up ebp frame (ESP=EBP)
push 0FFFFFFFFh ; [EBP-4] push initial state
push offset SEH_1000BF50 ; [EBP-8] SEH handler for the function
mov eax, large fs:0 ; read SEH chain list head
push eax ; [EBP-C] pointer to previous SEH record
sub esp, 14h ; allocate space for local vars and move to the saved registers area.
push ebx ; [EBP-18] save ebx
push esi ; [EBP-1C] save esi
push edi ; [EBP-20] save edi
mov eax, ___security_cookie
xor eax, ebp ; xor the cookie to make it harder to forge
push eax ; EBP-24 push XOR'ed cookie
lea eax, [ebp-0Ch] ; eax = &SEH_record
mov large fs:0, eax ; insert our SEH entry at start of list
最终的堆栈框架布局:
EBP-30 xored EH cookie
EBP-2C saved edi
EBP-28 saved esi
EBP-24 saved ebx
EBP-20 <local variables>
EBP-0C SEH pointer to previous record\
EBP-08 SEH handler | extended SEH record
EBP-04 EH state /
EBP+00 saved EBP
EBP+04 return address
如果发生异常,则在跳转到执行C ++异常处理或堆栈展开的
___CxxFrameHandler3
之前,在特定于功能的SEH处理程序中进行检查: br /> (1)获取SEH处理程序的第二个参数(
EstablisherFrame
),它指向函数中存储在EBP-C
中的活动SEH记录,因此我们通过0Ch
对其进行调整以获取原始EBP
值它用于与cookie值(最初存储在[EBP-30h]
或SEH记录的-24h)进行异或,然后将异或结果与__security_check_cookie()
的期望值进行比较。决定不需要保护返回地址,因为该函数中没有缓冲区(请参见MSDN中的“ GS缓冲区”),并且任何其他覆盖都将破坏EH c ookie,如果出现异常将被检测到。顺便说一句,位于
state
的[ebp-4]
变量唯一标识函数执行中的状态。这允许C ++异常处理程序(例如__CxxFrameHandler
)销毁由于异常而离开其作用域的所有自动对象,并将状态展开为起始对象(通常为-1)。因此,此异常处理程序设置不对应于“ try / catch块”,而是由编译器为整个功能添加的。但是,状态转换(对try级别变量的写入可能对应于try块边界(或仅是作用域边界)。 EH),请查看有关该主题(及其参考文献)的文章。
评论
那是一篇非常有用的文章。我还是有点困惑。如果仅在异常期间调用处理程序,那么如何检测到修改后的返回地址?
–二十
18年8月29日在17:54
通常在功能结束时应该进行cookie检查。您可能切断了它。
–伊戈尔·斯科钦斯基♦
18年8月29日在17:55
...或者可能您的函数仅使用EH cookie(在异常处理程序中检查),而不使用GS cookie。
–伊戈尔·斯科钦斯基♦
18年8月29日在17:56
没有。我发布的结尾是函数内所有代码分支的交汇处。两者之间都是正常代码。可能是EH Cookie,TBH在阅读您的文章之前我什至都不知道这种事情。
–二十
18年8月29日在17:57
好吧,我想现在已经很完整了
–伊戈尔·斯科钦斯基♦
18年8月29日在20:46