我正在尝试了解此GS cookie实现的工作方式。根据本主题的阅读内容,在序幕过程中会设置一个cookie,然后在尾声中再次进行检查。好了,我可以看到cookie被设置了,但是它不像我在网上看到的示例。 :

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