如何实现__RTC_CheckEsp?

oll*_*dbg 7 c++ windows assembly

__RTC_CheckEsp是一个验证esp堆栈,寄存器正确性的调用.调用它以确保esp在函数调用中保存了值.

谁知道它是如何实现的?

Goz*_*Goz 7

那么对汇编程序的一点检查就可以了

0044EE35  mov         esi,esp 
0044EE37  push        3039h 
0044EE3C  mov         ecx,dword ptr [ebp-18h] 
0044EE3F  add         ecx,70h 
0044EE42  mov         eax,dword ptr [ebp-18h] 
0044EE45  mov         edx,dword ptr [eax+70h] 
0044EE48  mov         eax,dword ptr [edx+0Ch] 
0044EE4B  call        eax  
0044EE4D  cmp         esi,esp 
0044EE4F  call        @ILT+6745(__RTC_CheckEsp) (42BA5Eh) 
Run Code Online (Sandbox Code Playgroud)

这里有2行注意事项.首先注意0x44ee35它将esp的当前值存储到esi.

然后在函数调用完成后,它在esp和esi之间执行cmp.他们现在应该都是一样的.如果他们不是那么有人已经解开堆栈两次或没有解开它.

_RTC_CheckEsp函数如下所示:

_RTC_CheckEsp:
00475A60  jne         esperror (475A63h) 
00475A62  ret              
esperror:
00475A63  push        ebp  
00475A64  mov         ebp,esp 
00475A66  sub         esp,0 
00475A69  push        eax  
00475A6A  push        edx  
00475A6B  push        ebx  
00475A6C  push        esi  
00475A6D  push        edi  
00475A6E  mov         eax,dword ptr [ebp+4] 
00475A71  push        0    
00475A73  push        eax  
00475A74  call        _RTC_Failure (42C34Bh) 
00475A79  add         esp,8 
00475A7C  pop         edi  
00475A7D  pop         esi  
00475A7E  pop         ebx  
00475A7F  pop         edx  
00475A80  pop         eax  
00475A81  mov         esp,ebp 
00475A83  pop         ebp  
00475A84  ret              
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,首先要检查的是先前比较的结​​果是否"不相等",即esi!= esp.如果是这样,那么它会跳转到失败代码.如果它们相同则函数只返回.


Ton*_*ion 2

如果您擅长汇编,也许这会有所帮助:

jne (Jump if Not Equal) - 如果 ZERO 标志为 NZ (NotZero) 则跳转

_RTC_CheckEsp:
004C8690  jne         esperror (4C8693h) 
004C8692  ret              
esperror:
004C8693  push        ebp  
004C8694  mov         ebp,esp 
004C8696  sub         esp,0 
004C8699  push        eax  
004C869A  push        edx  
004C869B  push        ebx  
004C869C  push        esi  
004C869D  push        edi  
004C869E  mov         eax,dword ptr [ebp+4] 
004C86A1  push        0    
004C86A3  push        eax  
004C86A4  call        _RTC_Failure (4550F8h) 
004C86A9  add         esp,8 
004C86AC  pop         edi  
004C86AD  pop         esi  
004C86AE  pop         ebx  
004C86AF  pop         edx  
004C86B0  pop         eax  
004C86B1  mov         esp,ebp 
004C86B3  pop         ebp  
004C86B4  ret              
004C86B5  int         3    
004C86B6  int         3    
004C86B7  int         3    
004C86B8  int         3    
004C86B9  int         3    
004C86BA  int         3    
004C86BB  int         3    
004C86BC  int         3    
004C86BD  int         3    
004C86BE  int         3    
004C86BF  int         3   
Run Code Online (Sandbox Code Playgroud)

  • 他们这样做的原因是,如果 int 3 中发生无效跳转,那么代码将立即中断,您可以轻松地看到发生了无效跳转。 (7认同)
  • `int 3` 是一个字节,它是断点中断。因此,该字节值传统上用作函数之间的填充。(当然是 x86 特定的)。请注意,它是无法访问的,实际上零就足够了。 (3认同)