进入本次正题:

                           (二)[  C++ 之 友元关系  ]

来CPP代码:

代码:
#include "stdafx.h"
#include <iostream>

struct X;
struct Y
{
void f(X*);
};
struct X
{
private:
int i;
public:
void initialize();
friend void g(X*,int);
friend void Y::f(X*);
friend struct Z;
friend void h();
};

void X::initialize(){i=0;}
void g(X* x,int i){x->i = i;}
void Y::f(X* x){x->i = 9;}

struct Z
{
private:
int j;
public:
void initialize();
void g(X*);
};

void Z::initialize(){j = 8;}
void Z::g(X* x)
{
x->i += this->j;
}

void h(){X x;x.i = 4 ;}

int main(int argc, char* argv[])
{
X x; Y y; Z z;
__asm int 3
printf("sizeof X , Y , Z : %d %d %d\n",sizeof(x),sizeof(y),sizeof(z));
z.g(&x);
return 0;
}
////看反汇编 (Debug版本的)

00401409    6A 04           push 4
0040140B    6A 01           push 1                                   ; 还是注意,奇异抽象结构长度在此为1
0040140D    6A 04           push 4
0040140F    68 1C104300     push Lesson2.0043101C                    ; ASCII "sizeof X , Y , Z : %d %d %d",LF
00401414    E8 47700000     call Lesson2.printf
00401419    83C4 10         add esp,10
0040141C    8D45 FC         lea eax,dword ptr ss:[ebp-4]
0040141F    50              push eax
00401420    8D4D F4         lea ecx,dword ptr ss:[ebp-C]             ; 进入类成员函数之前,ecx传this指针是主旋律
00401423    E8 E2FBFFFF     call Lesson2.0040100A
00401428    33C0            xor eax,eax
0040142A    5F              pop edi
0040142B    5E              pop esi
0040142C    5B              pop ebx
0040142D    83C4 4C         add esp,4C
00401430    3BEC            cmp ebp,esp
00401432    E8 C96E0000     call Lesson2._chkesp
00401437    8BE5            mov esp,ebp
00401439    5D              pop ebp
0040143A    C3              retn

////下面也是Debug版本才有的,看看当前模块有什么函数一清二楚了.

00401005   /E9 26030000     jmp Lesson2.Z::initialize
0040100A   |E9 61030000     jmp Lesson2.Z::g
0040100F   |E9 AC030000     jmp Lesson2.h
00401014   |E9 77040000     jmp Lesson2.std::ctype<unsigned short>::>
00401019   |E9 12050000     jmp Lesson2.std::ctype<unsigned short>::>
0040101E   |E9 CD030000     jmp Lesson2.main
00401023   |E9 98020000     jmp Lesson2.g
00401028   |E9 53020000     jmp Lesson2.X::initialize
0040102D   |E9 BE020000     jmp Lesson2.Y::f

////

00401370 > 55              push ebp
00401371    8BEC            mov ebp,esp
00401373    83EC 44         sub esp,44
00401376    53              push ebx
00401377    56              push esi
00401378    57              push edi
00401379    51              push ecx
0040137A    8D7D BC         lea edi,dword ptr ss:[ebp-44]
0040137D    B9 11000000     mov ecx,11
00401382    B8 CCCCCCCC     mov eax,CCCCCCCC
00401387    F3:AB           rep stos dword ptr es:[edi]              ; 填充一下, 以后这些简单的就不说了.
00401389    59              pop ecx
0040138A    894D FC         mov dword ptr ss:[ebp-4],ecx             ; 第一个局部变量放this指针
0040138D    8B45 08         mov eax,dword ptr ss:[ebp+8]             ; 传进来的x的地址
00401390    8B08            mov ecx,dword ptr ds:[eax]               ; x.i 成员
00401392    8B55 FC         mov edx,dword ptr ss:[ebp-4]             ; this放到edx中
00401395    030A            add ecx,dword ptr ds:[edx]               ; ecx += this.j
00401397    8B45 08         mov eax,dword ptr ss:[ebp+8]             ; 传进来的x的地址, 执行了2遍
0040139A    8908            mov dword ptr ds:[eax],ecx               ; 完成赋值了,.
0040139C    5F              pop edi
0040139D    5E              pop esi
0040139E    5B              pop ebx
0040139F    8BE5            mov esp,ebp
004013A1    5D              pop ebp
004013A2    C2 0400         retn 4

再来看一下Release版本的:

////

00401097    6A 04           push 4
00401099    6A 01           push 1
0040109B    6A 04           push 4
0040109D    68 A0D04000     push Lesson2.0040D0A0                    ; ASCII "sizeof X , Y , Z : %d %d %d",LF
004010A2    E8 B82A0000     call Lesson2.00403B5F
004010A7    83C4 10         add esp,10
004010AA    8D45 FC         lea eax,dword ptr ss:[ebp-4]
004010AD    8D4D F8         lea ecx,dword ptr ss:[ebp-8]
004010B0    50              push eax
004010B1    E8 CAFFFFFF     call Lesson2.00401080
004010B6    33C0            xor eax,eax
004010B8    8BE5            mov esp,ebp
004010BA    5D              pop ebp
004010BB    C3              retn

////省了jmp 了. Release版本的就是简洁啊.

00401080    8B4424 04       mov eax,dword ptr ss:[esp+4]
00401084    8B09            mov ecx,dword ptr ds:[ecx]
00401086    0108            add dword ptr ds:[eax],ecx
00401088    C2 0400         retn 4



小结:

C++的友元其实对于逆向来说没有多大价值, 它更多的是为了编译器服务的, 是与信息封装相反的一种思想,
它是作用于C++的编译器的, 友元的关键字friend 其实跟 extern 一样只是一个声明, 定义一个符号而已.

对于最终的exe, 还是ecx 传this指针是主旋律 . 还有就是一个类的多个成员函数编译器其实也是把它当成普通的
函数去编译而已, 是一样的. 只不过去调用一个对象的成员函数的时候, 会先传ecx进去, 然后在函数内部便于定位各数据成员.