首页 > 编程语言 >C++逆向分析——多态和虚表

C++逆向分析——多态和虚表

时间:2023-04-09 10:55:09浏览次数:38  
标签:虚表 函数 子类 多态 C++ 地址 抽象类

虚表

上一章了解了多态,那么我们来了解一下多态在C++中是如何实现的。

了解本质,那就通过反汇编代码去看就行了,首先我们看下非多态的情况下的反汇编代码:

images/download/attachments/12714553/image2021-4-15_23-14-19.png

然后再来看下多态情况下的反汇编代码:

images/download/attachments/12714553/image2021-4-15_23-18-22.png

很明显这里多态的情况下会根据edx间接调用,而非多态则会直接调用。

那么我们来看下间接调用的流程是什么:

  1. ebp+8地址对应的值给到eax(ebp+8 也就是函数的参数 → 当前参数指针【父类指针】)

  2. eax地址对应的值给到edx(eax相当于当前对象的第一个成员)

  3. 调用edx地址对应的值,也就是子类对象的Print函数

但是这里很奇怪,第一个成员为什么就能是Print函数呢?跟我们之前理解的4个字节的参数完全不一样。

那么编译器到底是做了什么工作,才能根据我们传入的对象来进行间接调用的呢?这是因为虚表

只要有虚函数,不论多少个,对象的数据宽度就会比其原来多出4个字节,这四个字节我们称之为虚表。

images/download/attachments/12714553/image2021-4-15_23-54-33.png

images/download/attachments/12714553/image2021-4-15_23-54-26.png

那么虚表在哪呢?可以通过VC6来寻找虚标,先创建对象然后下断点运行查看,如下图中,可以很清晰的看见对象t除了继承Person父类的Age、Sex以及本身的Level成员外,还有一个__vfptr,上面有一个地址就是0x00422024,那这个地址就是虚表,这个表里面存储的就是函数的地址:

images/download/attachments/12714553/image2021-4-16_0-1-56.png

我们可以调出内存窗口查看一下:

images/download/attachments/12714553/image2021-4-16_0-6-6.png

这个存储的地址就是0x00401037,这时候切到反汇编代码就然后Ctrl+G输入跟进这个地址:

images/download/attachments/12714553/image2021-4-16_0-8-14.png

那这个地址就是Teacher的成员函数Print的地址。

虚表的结构:虚表中存储的都是函数地址,每个地址占用4个字节,有几个虚函数,则就有几个地址。

子类没有重写时,虚表中则只有父类自己的成员函数地址,反之,当子类重写虚函数时候,虚表中则存在父类自己的成员函数地址与子类重写的成员函数地址。

 

纯虚函数

 

之前学习过虚函数,也提到了纯虚函数,虽然纯虚函数语法很简单的,但是其比较难理解,所以在有一定的面向对象的基础时候再来学习会比较容易理解一些。

纯虚函数语法:

  1. 将成员函数声明为 virtual

  2. 该函数没有函数体,最后跟=0

class Base { public: virtual int Plus() = 0; }

语法不过多的阐述,之前也有写过;接下来我们要了解一个新的概念:抽象类。

抽象类有这几种特征:

  1. 含有纯虚函数的类,称之为抽象类

  2. 抽象类也可以包含普通的函数;

  3. 抽象类不能实例化(创建对象)。

那么问题来了,抽象类有什么意义呢?我们可以把抽象类看作是对子类的一种约束,或者认为其(抽象类)就是定义一种标准。

比如:淘宝,有很多店铺,虽然每个店铺卖的东西都不一样,但是他们同样都可以下单、评论、购物车,也就是说他们都遵守了这种标准规则;也就是说你可以把淘宝当作一个抽象类,其有很多成员:购物车、评论、商品展示区...但是他都没有定义,而是交给开淘宝店的人(子类)去根据标准规则定义。

images/download/attachments/12714553/image2021-4-17_16-20-55.png

而如果不按照这种标准呢来,那么假如要统计所有的数据就会非常麻烦,不便于管理。

标签:虚表,函数,子类,多态,C++,地址,抽象类
From: https://www.cnblogs.com/bonelee/p/17299993.html

相关文章

  • OS-Linux-Ubuntu22.04x64-Python-C++调用Python缺少Python.h
    OS-Linux-Ubuntu22.04x64-Python-C++调用Python缺少Python.h使用C或C++扩展Python扩展和嵌入Python解释器Python3.10.11Python/CAPI参考手册Python3.11.3Python/CAPI参考手册参考https://www.cnblogs.com/lidabo/p/17043302.htmlhttps://blog.csdn.net/z......
  • C++ Allocator
    C++Allocator该开始搞项目了,但是在搞项目之前,先搞一下C++的Allocator,因为项目中会用到。现在还不确定到底模仿哪个,jemalloc和tcmalloc,先看看吧。1.为什么需要Allocator其实和new/delete是等价的,但是可以屏蔽一些底层细节,因为不一定所有平台都提供统一的内存分配方式,所以需要......
  • 2023年第14届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组
    2023年第14届蓝桥杯大赛软件赛省赛C/C++大学B组试题A:日期统计(5)直接暴力,8个for+优化,2~5分钟跑完。答案:365点击查看代码#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;constintN=1e6+10,INF=0x3f3f3f3f;intmon[]={0,31,28,......
  • C++函数重载和对象
    函数的默认参数intfun(inta,intb=10,intc=20){returna+b+c;}intmain(){cout<<fun(10)<<endl;//当参数有值时也可以输出正确,如果程序员加了返回值就用程序员加入的值。}形参的数据从左到右当中间有参数后面也需要定义一个函数和声明只能实现一个;占位参数voidfun(int*a,int......
  • 第十四届蓝桥杯大赛软件赛省赛C/C++大学生B组
    第十四届蓝桥杯大赛软件赛省赛C/C++大学生B组试题A:日期统计A题直接枚举即可,枚举日期,暴力匹配#include<iostream>#include<algorithm>#include<vector>usingnamespacestd;boolcheck(stringt){ if(t.substr(0,4)!="2023")returnfalse; stringmon=t.substr(4,2......
  • C++多核多线程同步实现
    使用MakefileC++11工程模拟dsp的多核同步逻辑,使用多线程模拟多核,多个线程通过C++11的条件变量实现同步。当某一线程执行到同步函数syn_func时,判断是否其他线程执行到此处了,若有其他线程没有执行到此处,本线程就应阻塞。当最后一个线程执行到同步函数时,通知所有线程解除阻塞,实现......
  • C++,OpenCV图像像素运算(6)
    参与算术运算图像的数据类型、通道数目、大小必须相同算术运算加法:addvoidadd(InputArraysrc1,InputArraysrc2,OutputArraydst,InputArraymask=noArray(),intdtype=-1);/******************************************************************** src1: 输入图1* ......
  • C++primer第五章
    5.1 简单语句表达式语句的作用是执行表达式并丢弃掉求值结果。最简单h的语句是空语句,空语句中只有一个单独的分号。复合语句是指用花括号括起来的语句和声明序列,复合语句也被称为块。一个块就是一个作用域。5.2 语句作用域定义在控制结构内的变量作......
  • C++ 并发编程实战 第二章 线程管控
    第二章线程管控std::thread简介构造和析构函数///默认构造///创建一个线程,什么也不做thread()noexcept;///带参构造///创建一个线程,以A为参数执行F函数template<classFn,class...Args>explicitthread(Fn&&F,Args&&...A);///拷贝构造(不可用)thread......
  • C++primer第四章表达式
    4.1 基础4.1.1 基本概念当一个对象作为右值时,用的是对象的值。当一个对象作为左值时,用的是对象的身份(在内存中的位置)。如果表达式的求值结果是左值,decltype作用于该表达式得到一个引用类型。4.1.2 优先级与结合律括号优先级比较高。在第四章结尾处附上了......