学无止尽,积土成山,积水成渊-《C++反汇编与逆向分析技术揭秘》 读书笔记
3.其他
34 }
1. 内存分布
1 类Derive对象 2 0019FD30 0139583C =>.rdata:const Derive::`vftable'
3 0019FD34 00000001 =>Base.nBase 4 0019FD38 00000002 =>Derive.nDerive 5
6 虚函数表 7 0139583C 01391163 Base::f(void) 8 01395840 0139110E Derive::g(void) ;Derive类重写(override)后的函数地址 9 01395844 013911AE Derive::h(void) ;Derive类重写(override)后的函数地址
2. 构造函数
1 pop ecx ;=>this指针出栈
2 mov [ebp+this], ecx ;=>保存this指针
3 mov ecx, [ebp+this] 4 call j_??0Base@@QAE@XZ ;=>调用基类构造函数Base::Base(void)
5 mov eax, [ebp+this] ;=>eax=this指针
6 mov dword ptr [eax], offset ??_7Derive@@6B@ ;=>初始化虚表指针为const Derive::`vftable'
3. 析构函数
1 pop ecx ;=>this指针出栈
2 mov [ebp+this], ecx ;=>保存this指针
3 mov eax, [ebp+this] 4 mov dword ptr [eax], offset ??_7Derive@@6B@ ;=>重置虚表指针为const Derive::`vftable'
5 mov esi, esp 6 push offset aDerive ; "~Derive"
7 call ds:__imp__printf 8 add esp, 4
9 cmp esi, esp 10 call j___RTC_CheckEsp 11 mov ecx, [ebp+this] ;=>ecx传参this指针
12 call j_??1Base@@QAE@XZ ;=>调用基类析构函数 Base::~Base(void)
1 #include <iostream> 2 using namespace std; 3
4 class Base1 { 5 public:
6 virtual void f() { cout << "Base1::f" << endl; }
7 virtual void g() { cout << "Base1::g" << endl; }
8 Base1(){b1 = 1; printf("Base1"); }
9 ~Base1(){ printf("~Base1"); }
10 private:
11 int b1; 12
13 }; 14
15 class Base2 { 16 public:
17 virtual void f() { cout << "Base2::f" << endl; }
18 virtual void g() { cout << "Base2::g" << endl; }
19 Base2(){b2 = 2; printf("Base2"); }
20 ~Base2(){ printf("~Base2"); }
21 private:
22 int b2; 23 }; 24
25 class Derive : public Base1, public Base2{ 26 public:
27 virtual void f() { cout << "Derive::f" << endl; }
28 virtual void g1() { cout << "Derive::g1" << endl; }
29 Derive(){ d1 = 3; printf("Derive"); }
30 ~Derive(){ printf("~Derive"); }
31 private:
32 int d1; 33
34 }; 35
36 typedef void(*Fun)(void); 37
38 int main() 39 { 40
41 Derive d; 42 Base1 *b1 = &d; 43 b1->f(); 44 b1->g(); 45 Base2 *b2 = &d; 46 b2->f(); 47 b2->g(); 48 return 0; 49 }
1.内存分布
;内存布局
0019FA0C 008F584C ;=>.rdata:const Derive::`vftable'{for `Base1'} 第一个虚表
0019FA10 00000001 ;=>Base1.b1
0019FA14 008F583C ;=>.rdata:const Derive::`vftable'{for `Base2'} 第二个虚表
0019FA18 00000002 ;=>Base2.b2
0019FA1C 00000003 ;=>Derive.d1
;第一个虚函数表Derive::`vftable'{for `Base1'}
00FB584C 00FB1041 ;=>Derive::f(void), Dervie类重写(override)后的函数地址
00FB5850 00FB1118 ;=>Base1::g(void)
00FB5854 00FB111D ;=>Derive::g1(void), Derive类中新添加的虚函数地址
;第二个虚函数表Derive::`vftable'{for `Base2'}
00FB583C 00FB1113 ;=>Base2::g(void)
00FB5840 00FB1028 ;=>[thunk]:Derive::f`adjustor{8}' (void)
↓ ;追踪地址:00FB1028
00FB1028 jmp ?f@Derive@@W7AEXXZ ;=>[thunk]:Derive::f`adjustor{8}' (void)
↓ ;追踪函数:?f@Derive@@W7AEXXZ
00FB1F30 ?f@Derive@@W7AEXXZ proc near 00FB1F30 sub ecx, 8 ;=>调整this指针为this+8,即ecx-->Derive::`vftable'{for `Base2'}
00FB1F33 jmp j_?f@Derive@@UAEXXZ ;=>Derive::f(void),即Derive类重写后的函数地址
2.构造函数
1 00FB14D9 mov [ebp-4], ecx ;=>this指针保存在esp-4处
2 00FB14DC mov ecx, [ebp-4] ;=>ecx获得this指针
3 00FB14DF call j_??0Base1@@QAE@XZ ;=>调用构造函数 Base1::Base1(void)
4 00FB14E4 mov ecx, [ebp-4] ;=>ecx获得this指针
5 00FB14E7 add ecx, 8 ;=>ecx获得this+8
6 00FB14EA call j_??0Base2@@QAE@XZ ;=>调用构造函数 Base2::Base2(void)
7 00FB14EF mov eax, [ebp-4] ;=>eax获得this指针
8 00FB14F2 mov dword ptr [eax], offset ??_7Derive@@6BBase1@@@ ;=>初始化第一个虚表指针为const Derive::`vftable'{for `Base1'}
9 00FB14F8 mov eax, [ebp-4] ;=>eax获得this指针
10 00FB14FB mov dword ptr [eax+8], offset ??_7Derive@@6BBase2@@@ ;=>初始化第二个虚表指针const Derive::`vftable'{for `Base2'}
11 00FB1502 mov eax, [ebp-4] ;=>eax获得this指针
12 00FB1505 mov dword ptr [eax+10h], 3
13 00FB150C push offset Format ; "Derive"
14 00FB1511 call ds:__imp__printf 15 00FB1517 add esp, 4
3.析构函数
00FB17C9 mov [ebp-4], ecx ;=>this指针保存在esp-4处
00FB17CC mov eax, [ebp-4] ;=>ecx获得this指针
00FB17CF mov dword ptr [eax], offset ??_7Derive@@6BBase1@@@ ;=>重置第一个虚表指针为const Derive::`vftable'{for `Base1'}
00FB17D5 mov eax, [ebp-4] 00FB17D8 mov dword ptr [eax+8], offset ??_7Derive@@6BBase2@@@ ;=>重置第二个虚表指针为const Derive::`vftable'{for `Base2'}
00FB17DF push offset aDerive ; "~Derive"
00FB17E4 call ds:__imp__printf 00FB17EA add esp, 4
00FB17ED mov ecx, [ebp-4] ;=>ecx获得this指针
00FB17F0 add ecx, 8 ;=>ec;得this+8
00FB17F3 call j_??1Base2@@QAE@XZ ;=>调用虚构函数Base2::~Base2(void)
00FB17F8 mov ecx, [ebp-4] ;=>ecx获得this指针
00FB17FB call j_??1Base1@@QAE@XZ ;=>调用虚构函数Base1::~Base1(void)
4.虚函数调用
;Base1 *b1 = &d;
00FB1431 lea eax, [ebp-14h] ;=>eax获得this指针
00FB1434 mov [ebp-18h], eax ;=>局部变量b1赋值为this指针
;b1->f();
00FB1437 mov eax, [ebp-18h] ;=>eax获得b1值
00FB143A mov edx, [eax] ;=>edx指向第一个虚表
00FB143C mov ecx, [ebp-18h] ;=>ecx传递this指针
00FB143F mov eax, [edx] ;=>eax获得成员函数Derive::f(void)的地址
00FB1441 call eax ;=>调用成员函数Derive::f(void)
;b1->g();
00FB1443 mov eax, [ebp-18h] ;=>eax获得b1值
00FB1446 mov edx, [eax] ;=>edx指向第一个虚表
00FB1448 mov ecx, [ebp-18h] ;=>ecx传递this指针
00FB144B mov eax, [edx+4] ;=>eax获得成员函数Derive::g(void)的地址
00FB144E call eax ;=>调用成员函数Derive::g(void)
;Base2 *b2 = &d;
00FB1457 lea ecx, [ebp-14h] ;=>ecx获得this指针
00FB145A add ecx, 8 ;=>ecx=this+8指向第二个虚表
00FB145D mov [ebp-64h] ;=>保存ecx到临时变量中
00FB1460 jmp short loc_FB1469;----|
;|
00FB1469 mov edx, [ebp-64h];<----|
00FB146C mov [ebp-1Ch], edx ;=>局部变量b2在栈[ebp-1Ch],赋值为this+8,指向第二个虚表
;b2->f();
00FB146F mov eax, [ebp-1Ch] ;=>eax获得b2值
00FB1472 mov edx, [eax] ;=>edx获得指向第二个虚表
00FB1474 mov ecx, [ebp-1Ch] ;=>ecx传参this+8
00FB1477 mov eax, [edx+4] ;=>eax为第二个虚表的第二个元素=>[thunk]:Derive::f`adjustor{8}' (void),然后间接调用Derive::f(void)
00FB147A call eax ;b2->g();
00FB147C mov eax, [ebp+b2] ; =>eax获得b2值
00FB147F mov edx, [eax] ;=>edx获得指向第二个虚表
00FB1481 mov ecx, [ebp+b2] ;=>ecx传参this+8
00FB1484 mov eax, [edx] ;=>eax为第二个虚表的第一个元素=>Base2::g(void)
00FB1486 call eax ;=>调用Base2::g(void)