安卓c++虚函数解密

来源:互联网 发布:类似于柏拉图软件 编辑:程序博客网 时间:2024/06/03 21:08
0x00 搭建环境
使用arm-none-linux-gnueabi-gcc 编译程序
下载链接: arm-2010.09-50-arm-none-linux-gnueabi


编译程序
1)  sudo gedit ~/.bashrc
2)  在文件末尾添加如下的一行
export PATH=$PATH:/....../....../arm-2010.09-50/bin
3)  保存文件并退出
4)  运行命令 source ~/.bashrc

5)  用命令行验证一下是否成功: arm-none-linux-gnueabi-gcc --version。'

6)  编译: arm-none-linux-gnueabi-g++ -static hello.cpp -o hello


0x01 无继承

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

class BaseA

{

private:

         int baseA_field;

public:

         BaseA(int baseA_field);

         ~BaseA();

         virtual void baseA_virtual_1()

         {

                   printf("[-] BaseA::baseA_virtual_1()\n");

         }

         virtual void baseA_virtual_2()

         {

                   printf("[-]BaseA::baseA_virtual_2()\n");

         }

         virtual void baseA_virtual_3()

         {

                   printf("[-]BaseA::baseA_virtual_3()\n");

         }

};

BaseA::BaseA(intbaseA_field)

{

         printf("[+] BaseA constructorcalled\n");

         this->baseA_field = baseA_field;

}

BaseA::~BaseA()

{

         printf("[+] BaseA destructorcalled\n\n");

}

 

int main(int argc,char *argv[])

{

         getchar();

         BaseA *baseA = new BaseA(1);

         baseA->baseA_virtual_2();

         delete baseA;

         return 0;

}

F5反编译的结果


初步分析:

(*(*v1 + 4))(v1)

v1: this指针

*v1: 虚表指针

*v1 + 4: 虚表项2指针

(*(*v1 + 4)): 虚函数2指针

(*(*v1 + 4))(v1): 虚函数2调用,只有1个this指针参数


申请对象空间



调用构造函数


C++对象的内存布局为: 虚表指针 + 成员变量

 

跟随虚表指针,可以看到具体的虚表项(里面是虚函数指针)


每一项占4个字节


调用虚函数




0x02单继承、无重写虚函数

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

class BaseA

{

private:

         int baseA_field;

public:

         BaseA(int baseA_field);

         ~BaseA();

         virtual void baseA_virtual_1()

         {

                   printf("[-]BaseA::baseA_virtual_1()\n");

         }

         virtual void baseA_virtual_2()

         {

                   printf("[-]BaseA::baseA_virtual_2()\n");

         }

         virtual void baseA_virtual_3()

         {

                   printf("[-]BaseA::baseA_virtual_3()\n");

         }

};

BaseA::BaseA(intbaseA_field)

{

         printf("[+] BaseA constructorcalled\n");

         this->baseA_field = baseA_field;

}

BaseA::~BaseA()

{

         printf("[+] BaseA destructorcalled\n\n");

}

 

 

class SubClass:public BaseA

{

private:

         int subClass_field;

public:

         SubClass(int subClass_field, intbaseA_field);

         ~SubClass();

         virtual void subClass_virtula_1()

         {

                   printf("[-] SubClass::subClass_virtula_1()\n");

         }

         virtual void subClass_virtula_2()

         {

                   printf("[-]SubClass::subClass_virtula_2()\n");

         }

         virtual void subClass_virtula_3()

         {

                   printf("[-]SubClass::subClass_virtula_3()\n");

         }

};

SubClass::SubClass(intsubClass_field, int baseA_field) : BaseA(baseA_field)

{

         printf("[+] SubClass constructorcalled\n");

         this->subClass_field =subClass_field;

}

SubClass::~SubClass()

{

         printf("[+] SubClass destructorcalled\n\n");

}

 

int main(int argc,char *argv[])

{

         getchar();

         SubClass *subClass = new SubClass(2,1);

         subClass->subClass_virtula_3();

         delete subClass;

         return 0;

}


F5反汇编



申请对象空间




调用构造函数


C++对象的内存布局为: 虚表指针 + 父类成员变量 + 子类成员变量


虚表内容



子类虚函数跟在父类虚函数后面

 

调用虚函数subClass_virtual_3




0x03 单继承、有重写虚函数

申请对象空间



构造函数


C++对象的内存布局为: 虚表指针 + 父类成员变量 + 子类成员变量



虚表内容


父类被覆盖,一共只有5项


调用虚函数baseA_virtual_2()




0x04 多继承、无重写虚函数

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

class BaseA

{

private:

         int baseA_field;

public:

         BaseA(int baseA_field);

         ~BaseA();

         virtual void virtual_1()

         {

                   printf("[-]BaseA::virtual_1()\n");

         }

         virtual void virtual_2()

         {

                   printf("[-]BaseA::virtual_2()\n");

         }

         virtual void baseA_virtual_3()

         {

                   printf("[-]BaseA::baseA_virtual_3()\n");

         }

};

BaseA::BaseA(int baseA_field)

{

         printf("[+] BaseA constructorcalled\n");

         this->baseA_field = baseA_field;

}

BaseA::~BaseA()

{

         printf("[+] BaseA destructorcalled\n\n");

}

 

 

 

class BaseB

{

private:

         int baseB_field;

public:

         BaseB(int baseB_field);

         ~BaseB();

         virtual void virtual_1()

         {

                   printf("[-]BaseB::virtual_1()\n");

         }

         virtual void virtual_2()

         {

                   printf("[-]BaseB::virtual_2()\n");

         }

         virtual void baseB_virtual_3()

         {

                   printf("[-]BaseB::baseB_virtual_3()\n");

         }

};

BaseB::BaseB(intbaseB_field)

{

         printf("[+] BaseB constructorcalled\n");

         this->baseB_field = baseB_field;

}

BaseB::~BaseB()

{

         printf("[+] BaseB destructorcalled\n\n");

}

 

 

 

class BaseC

{

private:

         int baseC_field;

public:

         BaseC(int baseC_field);

         ~BaseC();

         virtual void virtual_1()

         {

                   printf("[-]BaseC::virtual_1()\n");

         }

         virtual void baseC_virtual_2()

         {

                   printf("[-]BaseC::baseB_virtual_3()\n");

         }

};

BaseC::BaseC(intbaseC_field)

{

         printf("[+] BaseC constructorcalled\n");

         this->baseC_field = baseC_field;

}

BaseC::~BaseC()

{

         printf("[+] BaseC destructorcalled\n\n");

}

 

 

 

class SubClass:public BaseA, public BaseB, public BaseC

{

private:

         int subClass_field;

public:

         SubClass(int subClass_field, intbaseA_field, int baseB_field, int baseC_field);

         ~SubClass();

         virtual void subClass_virtual_1()

         {

                   printf("[-]SubClass::subClass_virtula_1()\n");

         }

         virtual void subClass_virtual_2()

         {

                   printf("[-]SubClass::subClass_virtula_1()\n");

         }

         virtual void subClass_virtual_3()

         {

                   printf("[-]SubClass::subClass_virtula_3()\n");

         }

};

SubClass::SubClass(intsubClass_field, int baseA_field, int baseB_field, int baseC_field)

         : BaseA(baseA_field),BaseB(baseB_field), BaseC(baseC_field)

{

         printf("[+] SubClass constructorcalled\n");

         this->subClass_field =subClass_field;

}

SubClass::~SubClass()

{

         printf("[+] SubClass destructorcalled\n\n");

}

 

int main(int argc,char *argv[])

{

         getchar();

         SubClass *subClass = new SubClass(4, 3,2, 1);

         subClass->BaseA::virtual_1();   //静态调用

         subClass->baseB_virtual_3();

         subClass->subClass_virtual_1();

         delete subClass;

         return 0;

}

F5反汇编



构造函数



查看虚表内容




静态调用虚函数BaseA_virtual_1


静态函数地址固定,无需通过虚表寻找。



移动指针指向虚表第三项,即BaseB::baseB_virtual_3



调用虚函数BaseB::baseB_virtual_3



调用虚函数SubClass::subClass_virtual_1




0x05 多继承、有重写虚函数

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

class BaseA

{

private:

         int baseA_field;

public:

         BaseA(int baseA_field);

         ~BaseA();

         virtual void virtual_1()

         {

                   printf("[-]BaseA::virtual_1()\n");

         }

         virtual void virtual_2()

         {

                   printf("[-]BaseA::virtual_2()\n");

         }

         virtual void baseA_virtual_3()

         {

                   printf("[-]BaseA::baseA_virtual_3()\n");

         }

};

BaseA::BaseA(intbaseA_field)

{

         printf("[+] BaseA constructorcalled\n");

         this->baseA_field = baseA_field;

}

BaseA::~BaseA()

{

         printf("[+] BaseA destructorcalled\n\n");

}

 

 

class BaseB

{

private:

         int baseB_field;

public:

         BaseB(int baseB_field);

         ~BaseB();

         virtual void virtual_1()

         {

                   printf("[-]BaseB::virtual_1()\n");

         }

         virtual void virtual_2()

         {

                   printf("[-]BaseB::virtual_2()\n");

         }

         virtual void baseB_virtual_3()

         {

                   printf("[-]BaseB::baseB_virtual_3()\n");

         }

};

BaseB::BaseB(intbaseB_field)

{

         printf("[+] BaseB constructorcalled\n");

         this->baseB_field = baseB_field;

}

BaseB::~BaseB()

{

         printf("[+] BaseB destructorcalled\n\n");

}

 

 

class BaseC

{

private:

         int baseC_field;

public:

         BaseC(int baseC_field);

         ~BaseC();

         virtual void virtual_1()

         {

                   printf("[-]BaseC::virtual_1()\n");

         }

         virtual void baseC_virtual_2()

         {

                   printf("[-]BaseC::baseB_virtual_3()\n");

         }

};

BaseC::BaseC(intbaseC_field)

{

         printf("[+] BaseC constructorcalled\n");

         this->baseC_field = baseC_field;

}

BaseC::~BaseC()

{

         printf("[+] BaseC destructorcalled\n\n");

}

 

 

class SubClass:public BaseA, public BaseB, public BaseC

{

private:

         int subClass_field;

public:

         SubClass(int subClass_field, intbaseA_field, int baseB_field, int baseC_field);

         ~SubClass();

         virtual void virtual_1()

         {

                   printf("[-]SubClass::virtual_1()\n");

         }

         virtual void virtual_2()

         {

                   printf("[-]SubClass::virtual_2()\n");

         }

         virtual void baseC_virtual_2()

         {

                   printf("[-]SubClass::baseC_virtual_2()\n");

         }

         virtual void subClass_virtual_3()

         {

                   printf("[-]SubClass::subClass_virtual_3()\n");

         }

};

SubClass::SubClass(intsubClass_field, int baseA_field, int baseB_field, int baseC_field)

         : BaseA(baseA_field),BaseB(baseB_field), BaseC(baseC_field)

{

         printf("[+] SubClass constructorcalled\n");

         this->subClass_field =subClass_field;

}

SubClass::~SubClass()

{

         printf("[+] SubClass destructorcalled\n\n");

}

 

int main(int argc,char *argv[])

{

         getchar();

         SubClass *subClass = new SubClass(4, 3,2, 1);

         ((BaseA *)subClass)->virtual_1();

         ((BaseB *)subClass)->virtual_2();

         ((BaseC *)subClass)->virtual_1();

         ((BaseC*)subClass)->baseC_virtual_2();

         delete subClass;

         return 0;

}

F5反汇编



构造函数


C++对象内存布局:

第一继承对象(虚表指针+成员变量)  第二继承对象(虚表指针+成员变量)

第三继承对象(虚表指针+成员变量)  本身成员变量


虚表内容




调用虚函数((BaseA *)subClass)->virtual_1()



调用虚函数((BaseB *)subClass)->virtual_2();



调用虚函数((BaseC *)subClass)->virtual_1();


调用虚函数((BaseC *)subClass)->baseC_virtual_2();




0x06 总结

1). 单继承虚表结构:

1个虚表,按照父类虚函数 + 子类虚函数顺序排列

2). 多继承虚表结构:

多少个父类对应多少个虚表,子类的虚函数跟在第一个父类虚函数后面

3). 单继承虚函数调用过程:

this指针 -> 虚表指针 -> 移动虚表指针 -> 取虚函数 -> 调用虚函数(this指针)

4). 多继承虚函数调用过程:

移动this指针到父类部分 -> 父类虚表指针 -> 移动虚表指针 -> 取虚函数 -> 调用虚函数(this指针父类部分)

5). 有重写虚函数时,父类虚函数表对应函数指针被覆盖。

 

 

0x07 参考文献

从Arm汇编看Android C++虚函数实现原理

http://manyface.github.io/2016/06/21/cppVirtualMethod/




原创粉丝点击