學無止盡,積土成山,積水成淵-《C++反彙編與逆向分析技術揭祕》 讀書筆記ios
3.其餘ide
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. 構造函數this
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. 析構函數spa
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.構造函數code
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.析構函數orm
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)