C++:虚函数表Hook

Hook

在计算机编程中,"Hook"(钩子)是一种技术,用于拦截并修改特定事件或函数的执行流程。它允许程序员在特定的代码点插入自定义的代码,以实现对程序行为的修改、监视或增强。

虚函数表Hook

虚函数表(Virtual Function Table,简称VTable)Hook是一种利用C++的动态多态性机制来修改类行为的技术。在C++中,虚函数表是用于实现动态多态性的重要机制,每个对象都有一个指向虚函数表的指针,该表中存储了虚函数的地址,通过修改这个虚函数表(即替换虚函数表中存储的函数指针),我们可以改变类的行为,使其调用不同的函数。

虚函数表Hook使用

由于在内存中虚函数表具有保护属性,是不可写的,所以在Windows环境中我们要进行虚函数表Hook需要通过调用Windows API中的一个函数VirtualProtect来进行,这个函数可以帮助我们修改内存页面的保护属性,让我们可以对其进行写入操作。函数原型:

BOOL VirtualProtect(LPVOID lpAddress,SIZE_T dwSize,DWORD  flNewProtect,PDWORD lpflOldProtect
);
  • lpAddress:指向要修改保护属性的内存地址的指针。

  • dwSize:要修改的内存区域的大小(以字节为单位)。

  • flNewProtect

    :新的保护属性,可以是下列常量之一:

    • PAGE_READONLY:页面为只读。

    • PAGE_READWRITE:页面为可读写。

    • PAGE_EXECUTE:页面为可执行。

    • PAGE_EXECUTE_READ:页面为可执行和可读。

    • PAGE_EXECUTE_READWRITE:页面为可执行和可读写。

  • lpflOldProtect:指向保存原始保护属性的变量的指针。如果不需要原始保护属性,则可以将其设置为 nullptr

接着我们来看一个简单的示例:首先,定义了一个父类 Animal 和一个派生类 Cat。在 Animal 类中,定义了一个虚函数 eat(),并在派生类 Cat 中进行了重写。然后,定义了一个自定义的函数 MyFunc(),用于替换虚函数的实现。

//父类
class Animal
{
public:Animal(){};~Animal(){};//虚函数virtual void eat(){std::cout << "Animal Eat 函数" << std::endl;};
};
​
//派生类
class Cat : public Animal
{
public:Cat(){};~Cat(){};void eat(){std::cout << "cat Eat 函数" << std::endl;};
}
​
//Hook函数用于替换虚函数
void MyFunc() {std::cout << "this is My Hook" << std::endl;
}

接着在main函数中进行虚函数表Hook操作:

int main() {
​Animal * catObj = new Cat;
​int  nVfptr = *(int*)catObj;    //虚函数表地址DWORD oldFunAddress = 0;  //定义变量接收保存原始保护属性的变量的指针BOOL bFlag = VirtualProtect((void*)nVfptr,0x1000, PAGE_EXECUTE_READWRITE, &oldFunAddress);
​if (bFlag) {*(int*)nVfptr = (int)MyFunc;catObj->run();}delete catObj;system("pause");return 0;
}
​

先创建了一个指向 Cat 对象的 Animal 类指针 catObj

int nVfptr = *(int*)catObj;获取指向虚函数表的指针 nVfptr的地址,

VirtualProtect((void*)nVfptr,0x1000, PAGE_EXECUTE_READWRITE, &oldFunAddress);使用 VirtualProtect 将其对应的内存页属性设置为可读写。

`(void*)nVfptr 是将整数 nVfptr 转换为指针类型的操作。在这里,nVfptr 存储着指向虚函数表的指针的地址,但它的类型是 int。为了能够将其传递给 VirtualProtect 函数,我们需要将其转换为指针类型。

if (bFlag) {*(int*)nVfptr = (int)MyFunc;catObj->eat();
}

如果成功内存页属性设置为可读写,则将虚函数表中第一个函数指针(对应于 eat() 函数)修改为 MyFunc() 函数的地址。最后,调用 catObj->eat(),实际上会执行 MyFunc() 函数,而不是原本的 Cat 类中的 eat() 函数,最后执行结果如下:

虚函数表Hook是一种强大而灵活的技术,可以用于实现各种高级功能,但需要谨慎使用,并且要对目标程序的内部结构有深入的了解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/691920.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈夫曼编码(上)

文章目录 问题引入哈夫曼编码的编写总述步骤一步骤二步骤三步骤四 实现代码如下 问题引入 哈夫曼编码通常用于通信领域&#xff0c;是对较长信息进行压缩&#xff0c;然后发送到指定的位置&#xff0c;是为了节省发送信息占用的空间。 通常来说&#xff0c;如果信息中字符的重…

如何自定义Linux命令

说明&#xff1a;本文介绍如何将自己常用的命令设置为自定义的命令&#xff0c;以下操作在阿里云服务器CentOS上进行。 修改配置文件 修改配置文件前&#xff0c;先敲下面的命令查看当前系统配置的shell版本 echo $SHELL或者 echo $0区别在于&#xff0c;$SHELL查看的是系统…

合并连个有序链表(递归)

21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 2.讲解算法原理 2.1重复子问题 2.2只关心其中的一个子问题是如何解决的 2.3细节&#xff0c;递归出口 3.小总结 &#xff08;循环&#xff08;迭代&#xff09;VS 递归&#xff09;&#xff08;递归VS深搜&…

【数字IC设计】芯片设计中的RDC

RDC问题定义 在芯片设计中,RDC是reset domain crossing 的缩写,类似于CDC(clock domain crossing),由于现在SOC芯片是有很多ECUs组成,为了使整个系统能够快速从复位中恢复, 用户希望SOC里面每个ECU模块都可以有自己独立的异步复位信号,这样可以在出问题的时候只复位有错…

我研究了4年的小行星,在交论文的前一天......炸了!

绞尽脑汁地想选题&#xff0c;跟导师约谈&#xff0c;各种托关系找受访者&#xff0c;一次一次地试验&#xff0c;只为得到理想的数据&#xff0c;无数个挑灯夜读的夜晚&#xff0c;反反复复地Proof Read… 终于&#xff0c;你敲完了Conclusion的最后一个字… 看着word里显示的…

机器学习第37周周报 GGNN

文章目录 week37 GGNN摘要Abstract一、文献阅读1. 题目2. abstract3. 网络架构3.1 数据处理部分3.2 门控图神经网络3.3 掩码操作 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 传感器设置策略4.3.2 数据集4.3.3 实验设置4.3.4 模型参数设置4.3.5 实验结果 5. 结论 …

GDPU unity游戏开发 角色控制器与射线检测

在你的生活中&#xff0c;你一直扮演着你的角色&#xff0c;别被谁控制了。 小试 1. 创建一个角色控制器&#xff0c;通过键盘控制角色控制器的移动&#xff0c;角色控制器与家具发生碰撞后&#xff0c;通过Debug语句打印出被碰撞物体的信息(搜索OnControllerColliderHit的使用…

十个最适合论文写作的GPTs及其应用

文章目录 一、GPTs让一切皆有可能二、最适合论文写作的GPTs及其应用1、[Paper Search Engine](https://chat.openai.com/g/g-9v5gHG9Bo)2、[Academic Paper Specialist&#xff08;学术论文撰写专家&#xff09;](https://chat.openai.com/g/g-jryw3pfsH)3、[Paper Connect 论文…

01-win10安装Qt5

Qt5安装教程 下载Qt5官网下载(下载很慢)镜像网站下载(有些版本没有资源)迅雷下载(推荐)百度网盘下载(推荐)安装Qt5下载Qt5 官网下载(下载很慢) 【注意】:官网下载非常慢,没有镜像下载时常20+ Qt 官网有一个专门的资源下载网站,所有的开发环境和相关工具都可以从这…

实现二叉树的基本操作

博主主页: 码农派大星. 关注博主带你了解更多数据结构知识 1我们先来模拟创建一个二叉树 public class TestBinaryTreee {static class TreeNode{public char val;public TreeNode left;public TreeNode right;public TreeNode(char val) {this.val val;}}public TreeNode …

商家转账到零钱怎么开通?一步步教你玩转微信营销新利器

在数字化营销日新月异的今天&#xff0c;微信支付凭借其便捷、安全的特点&#xff0c;成为了商家不可或缺的支付工具。而其中的“商家转账到零钱”功能&#xff0c;更是为商家提供了一个全新的营销利器。今天&#xff0c;我们就来详细解读一下如何开通这一功能&#xff08;我处…

windows编译opencv4.9

opencv很多人在windows上编译感觉特别麻烦&#xff0c;没有linux下方便&#xff0c;设定以下三点&#xff0c;我们几乎会无障碍。 1 安装cuda&#xff0c;cudnn 安装好cuda&#xff0c;cudnn&#xff0c;把cudnn的头文件&#xff0c;库等等拷贝到cuda的安装目录下面&#xff…