14.ImGui-DX11虚表hook(一)-认识虚表
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:13.ImGui-搭建内部绘制的ImGui项目框架(无消息循环的简单ImGui实例)
虚表hook是通过dx11的交换链得到虚表,然后进行hook,交换链就是下图红框的东西
然后下图红框它的类型,然后按着CTRL然后鼠标左键单击下图红框位置
然后就能来到下图红框位置,这是一个c++类(类可以理解为一个结构),结构的名字是 IDXGISwapChain,这个结构用来描述DX11的交换链数据
如下图红框有很多函数它前面都有virtual,函数中有这个virtual都被称为虚函数,虚表就是用来存放虚函数的,然后代码编译成程序后(dll或exe)虚表的位置就会放在结构中第一个位置上,然后要hook的是Present函数,它是DX11用来渲染的函数
然后虚表很重要,所以下面开始介绍虚表,首先打开vs2022,创建一个控制台项目,如下图点击创建新项目
选择控制台应用,然后点击下一步
然后设置项目名和存放位置,然后点击创建
创建完后
然后写两个类,如下图红框,一个叫Object类,一个叫BOOS类,BOOS类继承Object类,上方的DX11交换链的结构是IDXGISwapChain类继承IDXGIDeviceSubObject类,跟下图的同理
然后使用上方的boos类
然后点击下图红框位置设置断点
设置了断点后的样子,有个小红点就表示设置了断点,当程序运行到设置了断点的位置后,会停下来
然后如下图红框当前是64位Debug模式
然后点击下图红框运行
运行后在断点位置停下来了
然后把内存窗口打开
内存窗口打开之后
然后下图红框的单词加&就可以得到boos的首地址了,然后boos是BOOS类型,也就是得到了BOOS类的首地址,&boos
然后在下图红框输入&boos,然后按回车键(Enter键)
然后就跳转到了boos的首地址,下图红框就是boos在内存中的样子了,现在还么有初始化所以全是CC
然后点击下图红框停止一下
然后改一下代码,如下图红框,改代码的愿意是为了在内存中让我们好区分,可以看到下图红框的数字前面有0x,这个表示当前数字是十六进制的,然后内存中的数据都会使用十六进制,如果不加0x就会是十进制,到了内存里我需要换算,不够直观,所以直接加上0x让它变成十六进制数方便在内存中观察
然后再次运行后,输入&boos来到它的首地址,如下图红框
然后点击下图红框,让它运行一行代码
按了上图红框的按钮后就会执行,下图红框的代码,然后boos就会被初始化,初始化后就有数据了,数据如下图绿框
如下图红框可以看到200和5000,0050是5000,0002是0200也就是200,要反着看,然后可以发现它先是Object类型的数据,也就是父类的数据,然后再是BOOS的数据
然后最前面的,如下图红框就是虚表(虚表的地址)
然后使用内存窗口访问虚表地址0x00007ff6c981ac50,它是十六进制数要带着0x,然后下图红框输入0x00007ff6c981ac50,然后按回车键
然后如下图红框就来到了虚表,然后可以看到全是数字不认识,不会看
然后鼠标左键右击选择转到反汇编
然后就能看到函数的地址了,如下图的框框,然后拿着这些地址去内存窗口里的虚表中找,就能认识了
如下图的框框
虚函数在虚表中的位置,如下图,可以发现它是以编写的顺序而定的
然后也就是说,一个类如果有虚函数,那么在它的首地址到首地址+8字节的位置是虚表地址,就是可以看到内存里是两个数一组两个数一组,两个数就是1个字节,如下图的8个框就是8字节,一个框表示1字节,两个数字表示1字节,00开头会默认省略不显示(可以在上方的实例中看到它省略了开头的0),64位是8字节,32位是4字节,这里用的是64位,32位和64位一样所以不展示32了
然后虚表结束后就是类中的数据,下图红框的就是数据,它们的数据是int类型,int类型是4字节,这种数据被称为成员变量
然后如果有继承关系,父(Object)类的数据会在前面,子(BOOS)类的数据会在后面
虚函数也是如此,父(Object)类的虚函数在前面,子(BOOS)类的虚函数在后面