一个典型的简单C++程序的反汇编分析

程序本身用VC编译:

 // virtualandoverloadding.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

class parent
{
public:
 int int1()
 {
  return 1;
 }
 virtual int int1(int x)
 {
  return x;
 }
 int int1(char c)
 {
  return c;
 }
};

class child:public parent
{
public:
 int int1(int x)
 {
  return x*2;
 }
};

int main(int argc, char* argv[])
{
 parent *p=new child();
 p->int1();
 p->int1(2);
 p->int1('c');
 return 0;
}
分析:

进入MAIN后
下面是动态的堆栈跟踪分析
PUSH EBP
 EBP
MOV EBP,ESP
 EBP,ESP->EBP
PUSH 0FFH
ESP ->0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
PUSH OFFSET _ehandler$_main(004109bb);SEH的构造,从堆栈图中特别清楚的.
ESP ->_ehandler$_main
   0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
mov eax,fs:[00000000]
push eax
ESP ->fs:[00000000]
   _ehandler$_main
   0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
mov  dword ptr fs:[0],esp 
sub esp,50h
esp ->...
          ...
   ...
   ...
   50H bytes
   ...
   fs:[00000000];这个结构已经呈现在我们面前
   _ehandler$_main
   0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
push ebx
push esi
push edi
esp ->edi
   esi
   ebx
   ...
          ...
   ...
   ...
   50H bytes
   ...
   fs:[00000000]
   _ehandler$_main
   0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
lea edi,[ebp-5Ch]
mov ecx,14h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
;注意这里的算法,开始分配的空间一共50H个字节共有80BYTE,所以这里用14H就是;20次循环
push 4
esp ->
   04h
   00h
   00h
   00h
   edi
   esi
   ebx
   ...
          ...
   ...
   ...
   50H bytes
   ...
   fs:[00000000]
   _ehandler$_main
   0FFH
   0FFH
   0FFH
   0FFH
EBP ->EBP
call operator new(00401360)
add esp 4;调用者恢复堆栈

进入operator new
operator new:
push ebp
mov ebp,esp
push 1
mov eax,dword ptr [cb]
push eax
call _nh_malloc (00401a70);malloc的参数是上面PUSH 4来的
add esp,8;临时空间的回收还是函数本身来负责的
pop ebp
ret
回到MAIN
mov dword ptr [ebp-18h],eax
mov dword ptr [ebp-4],0
cmp dword ptr [ebp-18h],0
je  main+54h (004010a4);这里用到了一个刚才忽视的单元EBP-4不知道为啥了,兄弟们知道的上啊...
mov ecx,dword ptr [ebp-18h]
call @ILT+15(child::child) (00401014)
终于进入了构造函数
child::child:
push ebp
mov ebp,esp
sub esp,44h
push ebx
push esi
push edi
push ecx;其实这里使用ecx来传递参数有些fastcall的意思了
lea edi,[ebp-44h]
mov ecx,11h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi];故技重施?唉...
pop ecx
mov dword ptr [ebp-4],ecx
mov ecx,dword ptr [ebp-4];这里编译器犯傻了,呵呵,倒腾了一次ECX
call @ILT+5(parent::parent) (0040100a);调用了父类构造器
;不怕累的继续跟我来
parent::parent:
push ebp
mov ebp,esp
sub esp,44h
push ebx
push esi
push edi
push ecx
lea edi,[ebp-44h]
mov ecx,11h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
pop ecx
mov dword ptr [ebp-4],ecx
mov eax,dword ptr [ebp-4]
mov dword ptr [eax],offset parent::`vftable' (00422020);看,默认构造器最最核心的部分终于出现:初始化vtable
mov eax,dword ptr [ebp-4]
pop edi
pop esi
pop ebp
ret
回到CHILD构造器
mov eax,dword ptr [ebp-4]
mov dword ptr [eax],offset child::`vftable' (0042201c)
mov eax,dword ptr [ebp-4]
pop edi
pop esi
pop ebx
add esp,44h
cmp ebp,esp
call        __chkesp (00401850)
mov esp,ebp
pop ebp
ret
一阵漫游之后,我们回到MAIN中,把变量送入到该送的地方去
0040109F 89 45 E4             mov         dword ptr [ebp-1Ch],eax
004010A2 EB 07                jmp         main+5Bh (004010ab)
004010A4 C7 45 E4 00 00 00 00 mov         dword ptr [ebp-1Ch],0
004010AB 8B 45 E4             mov         eax,dword ptr [ebp-1Ch]
004010AE 89 45 EC             mov         dword ptr [ebp-14h],eax
004010B1 C7 45 FC FF FF FF FF mov         dword ptr [ebp-4],0FFFFFFFFh
004010B8 8B 4D EC             mov         ecx,dword ptr [ebp-14h]
004010BB 89 4D F0             mov         dword ptr [ebp-10h],ecx;变量p栖身之所
004010BE 8B 4D F0             mov         ecx,dword ptr [ebp-10h];最后居然有四处存放了NEW的返回指针,效率啊!我的天呢...
我们来看函数调用,注意虚函数的方式
004010C1 E8 58 FF FF FF       call        @ILT+25(parent::int1) (0040101e)
004010C6 8B F4                mov         esi,esp
004010C8 6A 02                push        2
004010CA 8B 55 F0             mov         edx,dword ptr [ebp-10h]
004010CD 8B 02                mov         eax,dword ptr [edx];查表动作
004010CF 8B 4D F0             mov         ecx,dword ptr [ebp-10h]
004010D2 FF 10                call        dword ptr [eax];虚函数,有趣的是,如果你直接用CHILD指针进行调用,编译器优化为静态调用
004010D4 3B F4                cmp         esi,esp
004010D6 E8 75 07 00 00       call        __chkesp (00401850)
004010DB 6A 63                push        63h
004010DD 8B 4D F0             mov         ecx,dword ptr [ebp-10h]
004010E0 E8 2A FF FF FF       call        @ILT+10(parent::int1) (0040100f)
准备退出了...
004010E5 33 C0                xor         eax,eax
004010E7 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch]
004010EA 64 89 0D 00 00 00 00 mov         dword ptr fs:[0],ecx;先恢复SEH
004010F1 5F                   pop         edi
004010F2 5E                   pop         esi
004010F3 5B                   pop         ebx;寄存器退栈
004010F4 83 C4 5C             add         esp,5Ch
004010F7 3B EC                cmp         ebp,esp;释放临时空间
004010F9 E8 52 07 00 00       call        __chkesp (00401850)
004010FE 8B E5                mov         esp,ebp
00401100 5D                   pop         ebp
00401101 C3                   ret

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值