设为首页 加入收藏

TOP

12.1 识别类和类之间的关系(9)
2013-10-07 14:31:15 来源: 作者: 【 】 浏览:61
Tags:12.1 识别 类和 之间 关系

12.1 识别类和类之间的关系(9)

我们可以借此得到派生关系,在构造函数中先填写父类的虚表,然后按继承的层次关系逐层填写子类的虚表,由此可以判定vTable_40C0DC是父类的虚表,vTable_40C0D0是子类的虚表。以写入虚表的指令为界限,可以粗略划分出父类的构造函数和子类的构造函数的实现代码,但是细节上要按照程序逻辑找到界限之内其他函数传递参数的几行代码,并排除在外,如下所示:

  1. ; 先定位到new调用的正确分支处  
  2. .text:00401099     call  2@YAPAXI@Z ; operator new(uint) ; 调用new  
  3. .text:0040109E     mov esi, eax  
  4. .text:004010A0     add esp, 4  
  5. .text:004010A3     mov [esp+14h+var_10], esi  
  6. .text:004010A7     test esi, esi    ; 判定new调用后的返回值  
  7. .text:004010A9     mov [esp+14h+var_4], 0  
  8. .text:004010B1     jz  short loc_4010F2 ; 返回值为0,则跳转到错误逻辑处  
  9. ; 从这里开始就是正确的逻辑,同时也是父类构造函数的起始代码处  
  10. .text:004010B3     mov ecx, esi  
  11. .text:004010B5     mov dword ptr [esi], offset vTable_40C0DC  
  12. .text:004010BB     call ds:pfnGetCPerson  
  13. .text:004010C1     push eax  
  14. .text:004010C2     push offset Format ; "%s::ShowSpeak()\r\n"  
  15. .text:004010C7     call _printf  
  16. .text:004010CC     add esp, 8  
  17. ; 注意这里的传参(this指针),从这里开始就不是父类的构造函数实现代码了  
  18. .text:004010CF     mov ecx, esi  
  19. .text:004010D1     mov byte ptr [esp+14h+var_4], 1  
  20. .text:004010D6     mov dword ptr [esi], offset vTable_40C0D0  
  21. .text:004010DC     call ds:pfnGetCChinese  
  22. .text:004010E2     push eax  
  23. .text:004010E3     push offset Format ; "%s::ShowSpeak()\r\n"  
  24. .text:004010E8     call _printf  
  25. .text:004010ED     add esp, 8  
  26. ; new调用的正确分支末尾,同时也是子类构造函数的结束处  
  27. .text:004010F0     jmp short loc_4010F4 

继续看后面的代码:
  1. .text:004010F4  
  2. .text:004010F4 loc_4010F4: ; CODE XREF: _main+70↑j  
  3. .text:004010F4     mov eax, [esi] ; 取得虚表指针  
  4. .text:004010F6     mov ecx, esi ; 传递this指针  
  5. .text:004010F8     mov [esp+14h+var_4], 0FFFFFFFFh ; 修改计数器  
  6. .text:00401100     call dword ptr [eax+4] ; 调用虚表第二项的函数 

分析一下这里的虚函数调用,先看看最后一次写入虚表的地址,单击esi,往上观察高亮处,寻找最后一次写入的指令,如图12-3所示。
 
(点击查看大图)图12-3 寻找最后一次写入虚表的指令
细心的读者一定找到了!没错,正是004010D6地址处!指令“call dword ptr [eax+4]”揭示出虚表中至少有两个元素。接下来分析在004010D6处写入虚表vTable_40C0D0中的第二项内容到底是什么。
  1. .rdata:0040C0D0 vTable_40C0D0 dd offset sub_4011C0 ; 
    虚表偏移0处,也就是虚表的第一项  
  2. .rdata:0040C0D4 off_40C0D4 dd offset sub_401140 ; 
    虚表偏移4处,也就是虚表的第二项  
  3. .rdata:0040C0D8 pfnGetCChinese dd offset GetCChinese ; 
    现在不能确定这一项是否为虚表的内容 

双击sub_401140,得到以下代码:

  1. .text:00401140 sub_401140 proc near  
  2. ; 未赋值就直接使用ecx,说明ecx是在传递参数  
  3. .text:00401140     mov eax, [ecx] ; eax得到虚表  
  4. .text:00401142     call dword ptr [eax+8] ; 调用虚表第三项,形成了多态 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.1 识别类和类之间的关系(10) 下一篇12.1 识别类和类之间的关系(8)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: