标签:asm

以下是与标签 “asm” 相关联的文章

VC 栈结构分析

分析 VC 生成汇编代码的栈帧结构,并比较 release 和 debug 版本的不同。

release 版本

汇编分析

  • 去掉编译优化选项
  • 查看汇编代码

    int fib(int x)
    {
    004017E0  push        ebp  
    004017E1  mov         ebp,esp 
    004017E3  sub         esp,10h 
    004017E6  push        esi  
        int a = 1;
    004017E7  mov         dword ptr [a],1 
        int b = 2;
    004017EE  mov         dword ptr [b],2 
        int c = 3;
    004017F5  mov         dword ptr [c],3 
        int d = 4;
    004017FC  mov         dword ptr [d],4 
    
        if (x == 2)
    00401803  cmp         dword ptr [x],2 
    00401807  jne         fib+33h (401813h) 
        {
          return 1 + 1 + a;
    00401809  mov         eax,dword ptr [a] 
    0040180C  add         eax,2 
    0040180F  jmp         fib+75h (401855h) 
    00401811  jmp         fib+75h (401855h) 
        }
        else if (x == 1)
    00401813  cmp         dword ptr [x],1 
    00401817  jne         fib+43h (401823h) 
        {
          return 1 + 0 + b;
    00401819  mov         eax,dword ptr [b] 
    0040181C  add         eax,1 
    0040181F  jmp         fib+75h (401855h) 
    00401821  jmp         fib+75h (401855h) 
        }
        else if (x == 0)
    00401823  cmp         dword ptr [x],0 
    00401827  jne         fib+50h (401830h) 
        {
          return 0 + c;
    00401829  mov         eax,dword ptr [c] 
    0040182C  jmp         fib+75h (401855h) 
        }
        else
    0040182E  jmp         fib+75h (401855h) 
        {
          return fib(x - 1) + fib(x - 2) + d;
    00401830  mov         eax,dword ptr [x] 
    00401833  sub         eax,1 
    00401836  push        eax  
    00401837  call        fib (4017E0h) 
    0040183C  add         esp,4 
    0040183F  mov         esi,eax 
    00401841  mov         ecx,dword ptr [x] 
    00401844  sub         ecx,2 
    00401847  push        ecx  
    00401848  call        fib (4017E0h) 
    0040184D  add         esp,4 
    00401850  add         esi,dword ptr [d] 
    00401853  add         eax,esi 
        }
    }
    00401855  pop         esi  
    00401856  mov         esp,ebp 
    00401858  pop         ebp  
    00401859  ret
    
  • 分析生成汇编
    • 栈变量的次序是调整过的,防止被 hacker 利用。查看下面的机器指令, E7,EE,F5,FC,显然地址不连续。

      004017E7  mov         dword ptr [a],1 
      004017EE  mov         dword ptr [b],2 
      004017F5  mov         dword ptr [c],3 
      004017FC  mov         dword ptr [d],4
      
    • 被调函数的处理
      • 将 ebp 压栈,保护上层栈基址。

        004017E0  push        ebp
        
      • ebp 指向原来 esp 的位置,指向新的栈基址。

        004017E1  mov         ebp,esp
        
      • esp 留出栈变量的空间,指向新的栈顶。这里留出 4 个 int 的空间 16 个字节:

        004017E3  sub         esp,10h
        
      • 将 esi 压栈,esi 在 fibonaci 函数中被临时使用,这里压栈是为了保护原始值。

        004017E6  push        esi
        
      • 将 esi 退栈

        00401855  pop         esi
        
      • 将 ebp 退栈,恢复上层调用的栈基址

        00401858  pop         ebp
        
      • 将 esp 指向 ebp 的位置,恢复上层调用用栈顶

        00401856  mov         esp,ebp
        
      • 将函数地址退栈,PC 寄存器跳回调用函数

        00401859  ret
        
    • 调用函数的处理
      • 将参数压栈

        00401836  push        eax
        
      • 将函数地址压栈

        00401837  call        fib (4017E0h)
        

栈帧结构

高地址
para1
para2
func addr
ebp
save reg1
save reg2
stack var1
stack var2
低地址

栈帧分析

  • 重点查找 ebp, func addr 两个线索
    • ebp 要连接成串,每个 ebp 指向下一个 ebp;
    • func addr 要在 dll 或 exe 的地址空间内。

debug 版本

汇编分析

  • 生成汇编代码

    int fib(int x)
    {
    004113B0  push        ebp  
    004113B1  mov         ebp,esp 
    004113B3  sub         esp,0F0h 
    004113B9  push        ebx  
    004113BA  push        esi  
    004113BB  push        edi  
    004113BC  lea         edi,[ebp-0F0h] 
    004113C2  mov         ecx,3Ch 
    004113C7  mov         eax,0CCCCCCCCh 
    004113CC  rep stos    dword ptr es:[edi] 
        int a = 1;
    004113CE  mov         dword ptr [a],1 
        int b = 2;
    004113D5  mov         dword ptr [b],2 
        int c = 3;
    004113DC  mov         dword ptr [c],3 
        int d = 4;
    004113E3  mov         dword ptr [d],4 
    
        if (x == 2)
    004113EA  cmp         dword ptr [x],2 
    004113EE  jne         fib+4Ah (4113FAh) 
        {
          return 1 + 1 + a;
    004113F0  mov         eax,dword ptr [a] 
    004113F3  add         eax,2 
    004113F6  jmp         fib+8Ch (41143Ch) 
    004113F8  jmp         fib+8Ch (41143Ch) 
        }
        else if (x == 1)
    004113FA  cmp         dword ptr [x],1 
    004113FE  jne         fib+5Ah (41140Ah) 
        {
          return 1 + 0 + b;
    00411400  mov         eax,dword ptr [b] 
    00411403  add         eax,1 
    00411406  jmp         fib+8Ch (41143Ch) 
    00411408  jmp         fib+8Ch (41143Ch) 
        }
        else if (x == 0)
    0041140A  cmp         dword ptr [x],0 
    0041140E  jne         fib+67h (411417h) 
        {
          return 0 + c;
    00411410  mov         eax,dword ptr [c] 
    00411413  jmp         fib+8Ch (41143Ch) 
        }
        else
    00411415  jmp         fib+8Ch (41143Ch) 
        {
          return fib(x - 1) + fib(x - 2) + d;
    00411417  mov         eax,dword ptr [x] 
    0041141A  sub         eax,1 
    0041141D  push        eax  
    0041141E  call        fib (411154h) 
    00411423  add         esp,4 
    00411426  mov         esi,eax 
    00411428  mov         ecx,dword ptr [x] 
    0041142B  sub         ecx,2 
    0041142E  push        ecx  
    0041142F  call        fib (411154h) 
    00411434  add         esp,4 
    00411437  add         esi,dword ptr [d] 
    0041143A  add         eax,esi 
        }
    }
    0041143C  pop         edi  
    0041143D  pop         esi  
    0041143E  pop         ebx  
    0041143F  add         esp,0F0h 
    00411445  cmp         ebp,esp 
    00411447  call        @ILT+320(__RTC_CheckEsp) (411145h) 
    0041144C  mov         esp,ebp 
    0041144E  pop         ebp  
    0041144F  ret
    
  • 栈变量空间至少保留 0xF0 = 240 字节的空间

    004113B3  sub         esp,0F0h
    
  • 栈变量空间被初始化成 0xCC

    004113BC  lea         edi,[ebp-0F0h] 
    004113C2  mov         ecx,3Ch 
    004113C7  mov         eax,0CCCCCCCCh 
    004113CC  rep stos    dword ptr es:[edi]
    
  • 退栈时会作 ebp 检查,防止栈被破坏

    0041143F  add         esp,0F0h 
    00411445  cmp         ebp,esp 
    00411447  call        @ILT+320(__RTC_CheckEsp) (411145h)
    

栈帧结构

  • 栈变量的分配留有很大裕量,为每个 int 分配了 4*4=16 个字节空间。