发布时间:2026/7/14 13:30:50
C++逆向分析--虚函数(多态的前置) 先理解一件事在intel汇编层面来说直接调用和间接调用的区别。直接调用语法 call 地址 硬编码为 e8间接调用语法: call [ ...] 硬编码为: FF那么在C语法中实现多态的前提是父类需要实现多态的成员方法前面加入virtual。我们先来看一个例子这次试验用的是windows平台下的VS编译器不同编译器的细节是不一样的原理大差不差。#includeiostream using namespace std; class Base { public: void func1() { printf(这是func1); } virtual void func2() { printf(这是func2); } }; int main() { Base b1; b1.func1(); b1.func2(); return 0; }这个代码示例中我们只写了一个类并且用对象去调用成员方法。运行结果如下我们观察下汇编代码此时均为e8-call属于直接调用。接下来我们换一种调用方式我们通过指针的方式去调用对象方法:#includeiostream using namespace std; class Base { public: void func1() { printf(这是func1); } virtual void func2() { printf(这是func2); } }; int main() { Base b1; Base* p; p b1; p-func1(); p-func2(); return 0; }运行结果没有变化但是此时我们观察反汇编我们就发现了不一样的地方fun1就是普通的成员函数反汇编依然是那样。但是我们看加入关键字的virtual变成虚函数后汇编代码变化了。真正调用的其实是call eax这句汇编代码我们看到他的硬编码是FF D0。说明他是个间接调用。我们可以理解这段反汇编代码p是指向对象的首地址的也就是this指针。将this指针的第一项放入eax又将eax的第一项复制给edx此时将this指针给ecx如果是linux平台g编译this指针是赋值给rdi的 _x64情况下最后将edx的第一项赋值给eax。最后去执行。这段翻译可能有点绕。可以自己去理解下。现在我们知道虚函数如果是通过对象去调用和普通成员方法没什么区别但是如果通过指针或者引用去调用。那么他就是个间接调用。一些细节后面再讲。下面我们再分析一个问题这个类到底有多大。#includeiostream using namespace std; class Base { public: int a; int b; void func1() { printf(这是func1); } void func2() { printf(这是func2); } }; int main() { //Base b1; //Base* p; //p b1; //p-func1(); //p-func2(); printf(Base结构体大小为%d, sizeof(Base)); return 0; }这个问题应该很简单只算数据大小int类型是占4个字节因此这个Base对象的大小应该是8因为成员方法是在代码区的这里其实跟C语言的结构体没什么不一样的那如果现在我们将其中一个成员方法改成虚函数呢神奇的一幕发生了变成了12。那是不是说类中每多一个虚函数就会多4字节大小呢32位而言64位就是8我们将fun1也变成虚函数我们看到没有变化。也就是说跟你在类中定义多少个虚函数木的关系。那这多出来的4字节是个什么鬼东西呢这就是我们接下来要探究的东西。我们观察。现在没有任何函数的情况下我们的类是这样布局的。 0x00cffb80也就是b1对象的首地址。下面我们加入一个虚函数我们观察此时对象的内存布局什么都没有接着往下走再往下走再往下走我们发现对象首地址存的不再是1。而是一个地址。那这个地址是什么呢这就是我们接下来要探究的东西。写一个demo#includeiostream using namespace std; class Base { public: int a; int b; virtual void func1() { printf(这是func1); } }; int main() { Base b1; b1.a 1; b1.b 2; Base* p; p b1; p-func1(); return 0; }我们跟过去反汇编我们现在看这两行汇编的意思就很明朗了。1.mov eax [p] //将对象的this指针放入eax2.mov edx [eax] //将this指针首地址里面存的虚函数表放入edx3.mov ecx [p] //将this指针传给ecx3,mov eax ,[edx] //将虚函数表里的第一项放入eax4.call eax //调用fun1函数。相比看懂了上面的流程就明白了。总结图如下那我们能验证虚函数表中的函数就是我们的想要调用的函数嘛demo如下#includeiostream using namespace std; class Base { public: int a; int b; virtual void func1() { printf(这是func1\n); } }; int main() { Base b1; b1.a 1; b1.b 2; Base* p; p b1; p-func1(); printf(b1对象的地址%p\n, b1); printf(虚函数表地址%p\n, *((int*)b1)); printf(func1函数地址%p\n, *((int*)*((int*)b1))); int p2 *((int*)*((int*)b1)); _asm { call p2; } return 0; }这里因为我是用32位写的demo因此我们用内联汇编测试下。代码逻辑就是取出虚函数表中的第一项然后用汇编调用看是否和我们用指针调用的是同一个函数运行结果如下通过这个实验我们确实验证了虚函数表中存的就是我们的虚函数的地址。这也是C编译器实现多态的一个先提条件。

相关新闻

2026/7/14 13:30:50

3分钟极速部署:Windows 11 LTSC一键恢复微软商店的完美方案

3分钟极速部署:Windows 11 LTSC一键恢复微软商店的完美方案 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你是否在使用Windows 11 LTSC系…

2026/7/14 14:45:54

AI 辅助 Rust 内存泄漏排查:用 heaptrack 配合模型解读分配热点

AI 辅助 Rust 内存泄漏排查:用 heaptrack 配合模型解读分配热点 去年我的一个 Rust 长运行服务在跑了 48 小时后 RSS 从 50MB 涨到 2GB,我盯着 top 里的数字完全不知道该查哪里。Rust 不是"没有内存泄漏"吗?后来才知道,…

2026/7/14 14:45:54

useWallet()安全最佳实践:保护DApp用户资产的关键措施

useWallet()安全最佳实践:保护DApp用户资产的关键措施 【免费下载链接】use-wallet 👛 useWallet() All-in-one solution to connect a dapp to an Ethereum provider. 项目地址: https://gitcode.com/gh_mirrors/us/use-wallet useWallet() 是一…

2026/7/14 14:45:54

Cargo 编译性能优化实战:profile 分析 + 依赖裁剪 + 并行加速

Cargo 编译性能优化实战:profile 分析 依赖裁剪 并行加速 作为一个自学 Rust 的人,我最大的痛点就是编译慢。第一次编译一个中型项目,等了 8 分钟,我甚至怀疑是不是电脑有问题。后来才知道,Cargo 的编译慢不是偶然的…

2026/7/14 14:45:54

计算机毕业设计之基于Hadoop的热点新闻分析系统的设计与实现

近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,热点新闻分析系统利用计算机网络实现信息化管理,使整个热点新闻分析的发展和服务水平有显著提升。本文拟采用PyCharm开发工…

2026/7/14 12:47:32

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾在网易云音乐下载了心爱的歌曲&#…

2026/7/13 14:26:14

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境随着新能源汽车行业的快速发展,充电通信协议的标准化和测试验证变得尤为重要。GB/T 27930-2023作为中国智能充电协议的最新版本,对充电机与电动汽车之间的通信提出了更严格…

2026/7/13 18:07:53

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡 【免费下载链接】rtl8852be Realtek Linux WLAN Driver for RTL8852BE 项目地址: https://gitcode.com/gh_mirrors/rt/rtl8852be 还在为Linux系统无法识别RTL8852BE Wi-Fi 6网卡而烦恼吗?&#x1f…

2026/7/14 0:04:21

5分钟掌握足球PBR材质制作:Photoshop与Unity高效工作流

1. 项目概述:为什么是足球PBR材质?在游戏开发,尤其是体育竞技类游戏的制作中,一个看起来“对味”的足球,往往比我们想象中更重要。它不仅是赛场上的核心道具,更是玩家视觉焦点和沉浸感的重要来源。一个塑料…

2026/7/14 0:04:21

ChatGPT联网搜索失败,92%开发者误判为网络问题——真实根因竟是LLM推理会话上下文污染导致Search Agent进程静默退出(含strace复现脚本)

更多请点击: https://intelliparadigm.com 第一章:ChatGPT 联网搜索失败 当 ChatGPT 的联网搜索功能无法正常工作时,用户常遇到“搜索不可用”“未连接到互联网”或空白响应等现象。该问题并非模型本身缺陷,而是由权限配置、网络…

2026/7/14 12:47:31

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…