【问题标题】:How's __RTC_CheckEsp implemented?__RTC_CheckEsp 是如何实现的?
【发布时间】:2011-04-24 07:20:33
【问题描述】:

__RTC_CheckEsp 是一个验证esp、堆栈、寄存器正确性的调用。调用它是为了确保 esp 的值在函数调用中被保存。

有人知道它是如何实现的吗?

【问题讨论】:

    标签: c++ windows assembly


    【解决方案1】:

    如果你擅长 asm,也许这会有所帮助:

    jne (如果不相等则跳转) - 如果零标志为 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   
    

    【讨论】:

    • int 3是一个字节,是断点中断。因此,该字节值传统上用作函数之间的填充。 (当然是特定于 x86 的)。请注意,它是不可达的,实际上零就足够了。
    • 他们填充的原因是,如果在 int 3s 中发生无效跳转,那么代码将立即中断,您可以很容易地看到发生了无效跳转。
    【解决方案2】:

    稍微检查一下汇编器就会发现

    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) 
    

    这里有两行需要注意。首先注意在 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              
    

    如您所见,它首先检查的是先前比较的结​​果是否“不相等”,即 esi != esp。如果是这样,那么它会跳转到故障代码。如果它们相同,则函数简单地返回。

    【讨论】:

      猜你喜欢
      • 2011-04-26
      • 2015-05-22
      • 2015-04-22
      • 2020-07-31
      • 2016-04-17
      • 2013-08-23
      • 2014-05-27
      • 2016-04-16
      相关资源
      最近更新 更多