C++对象内存布局结构及虚函数调用实现分析(下)
创始人
2025-05-28 02:07:11
0

2.4 基于虚函数调用过程中可被利用的2种hook方法

2.4.1 hook虚函数

从图2.6中我们可以看到,虚函数表都存放在rdata段中,比如函数CPlayerObject::OnDamageHp函数存放在地址00402274中,如果我们把自己的函数地址替换到0x00402274处,那么当调用CPlayerObject::OnDamageHp函数时实际上调用到了我们自己的函数内部。我们就可以在函数内进行数据感知或者数据修改,甚至改变游戏逻辑等。比如通过this指针(ecx)我们可以知道哪个对象在被攻击,通过参数nDamageHp我们知道该次伤害掉血量有多少。如果是一个真实的游戏,那么我们基于这些信息就可以实现无敌(this指针为角色时可设置nDamageHp为0),也可以实现秒怪(如果this指针为怪物那么就可以设置nDamageHp为99999999等高伤害)。

2.4.2 hook虚表起始地址

从头图2.7虚函数调用过程总我们可以看到,虚函数调用是先获取虚函数表起始地址,也就是先mov eax, [ecx];这时候如果我们把虚函数起始地址替换从一个我们自己分配的内存块地址,然后把从地址0x00402250开始到0x00402278截止的内存数据拷贝到我们自己分配的内存中去,那么就相当于挟持了整个类的所有需函数。在我们自己构造的需函数表中想hook哪个函数就可以替换哪个函数的函数地址,替换方法和3.1介绍的方法类似。劫持整个函数虚表的好处是没有对代码段和rdata段进行修改,那么在分析过程中比较难发现。

三、c++函数调用基础

3.1 函数的调用约定

在开始之前,还是以代码说话,一般函数调用说明有如下几种方式,值需要参照c++声明和汇编层实现就可以很好的理解函数调用约定:
在这里插入图片描述
在这里插入图片描述

3.1.1 __cdecl调用约定

在这里插入图片描述
从函数调用约定的声明上来看,int __cdecl TestFunctionC(int a, int b, int c, int d, int e, int f)的调用约定我们声明为__cdecl调用方式。从汇编层实现,我们可以看到该方式具有以下特征:1、参数传递都通过堆栈传递;2、函数入栈顺序从右到左;3、堆栈平衡由调用者平衡,add esp, 18h这行命令就是用来平衡堆栈的。另外在IDA中我们看到int TestFunctionA(int a, int b, int c, int d, int e, int f)的调用方式也符合该原则,这说明在c\c++写的函数中如果不是类的成员函数,没做特殊调用声明,那么默认采用 __cdecl调用约定。

3.1.2 __stdcall调用约定

在这里插入图片描述
在这里插入图片描述
从函数调用约定的声明上来看,int __stdcall TestFunctionB(int a, int b, int c, int d, int e, int f)的调用约定我们声明为__stdcall 调用方式。从汇编层实现,我们可以看到该方式具有以下特征:1、参数传递都通过堆栈传递;2、函数入栈顺序从右到左;3、堆栈平衡由被调用者平衡,被调用函数内部函数结尾处retn 18h这行命令就是用来平衡堆栈的。

3.1.3 __fastcall 调用约定

在这里插入图片描述
在这里插入图片描述
从函数调用约定的声明上来看,int __fastcall TestFunctionD(int a, int b, int c, int d, int e, int f)的调用约定我们声明为__fastcall 调用方式。从汇编层实现,我们可以看到该方式具有以下特征:1、参数传递上第一个参数ecx传递,第二个参数edx传递,大于2个的部分都通过堆栈传递;2、函数入栈顺序从右到左;3、堆栈平衡由被调用者平衡,被调用函数内部函数结尾处retn 10h这行命令就是用来平衡堆栈的。由于前两个参数通过寄存器传递所以不需要堆栈平衡,函数内堆栈平衡值需要考虑大于2个参数的部分即可。

3.1.4 thiscall 调用约定

Thiscall 调用约定是唯一一个不需要特殊声明也无法人为指定的调用方式,它是指类的普通成员函数调用方式。该调用方式具有以下特点:1、ecx被使用,用作this指针的传递;2、其它参数一律通过堆栈传递,入栈顺序从右到左;3、堆栈平衡有被调用者平衡。

3.2 函数参数个数的确定技巧

基于堆栈传递的部分,要确定参数个数比较简单,通过堆栈平衡部分就可以快速确定参数个数。不过如果有参数是通过寄存器传递的,那么就需要一定技巧来确定寄存器里是否有参数传递进来。如下截图所示:
在这里插入图片描述
在这里插入图片描述
确定一个寄存器是否有被当成参数传递,那么最简单的方式就是看该寄存器在使用之前有没有进行数据保存和赋值。如图3.8所示,在对edi进行使用和赋值之前有进行push edi保存操作,所以edi就没有作为参数传递寄存器。如图3.9所示,edx没有进行赋值和保存数据,直接把edx里面的值复制给ebp+b参数了,所以edx是作为参数传递寄存器了。在分析游戏利用游戏函数实现功能的过程中edx就需要特别处理。

相关内容

热门资讯

有哪一些表达开心地表情包? 有哪一些表达开心地表情包?最喜欢的表达开心的表情包当属黄脸的表情了,简单的几种颜色表达出了丰富的心情...
2022大安法师现状 2022大安法师现状您是想问2022大安法师友改现状好吗?2022大安法师现状好,大安法师现状很好,...
纳睿雷达6月6日获融资买入81... 6月6日,纳睿雷达跌0.65%,成交额9518.01万元。两融数据显示,当日纳睿雷达获融资买入额81...
南芯科技6月6日获融资买入81... 6月6日,南芯科技跌0.60%,成交额1.80亿元。两融数据显示,当日南芯科技获融资买入额810.7...
傲对人生风雨情是什么意思? 傲对人生风雨情是什么意思?只有内心足够强大,才能心胸坦然的去面对人生路不熟的一切磨难。
三博脑科6月6日获融资买入37... 6月6日,三博脑科跌0.36%,成交额3.27亿元。两融数据显示,当日三博脑科获融资买入额3738....
新相微6月6日获融资买入489... 6月6日,新相微跌0.44%,成交额4608.29万元。两融数据显示,当日新相微获融资买入额489....
东和新材6月6日获融资买入16... 6月6日,东和新材涨0.70%,成交额4151.57万元。两融数据显示,当日东和新材获融资买入额16...
安达科技6月6日获融资买入28... 6月6日,安达科技跌0.16%,成交额2890.68万元。两融数据显示,当日安达科技获融资买入额28...
德尔玛6月6日获融资买入157... 6月6日,德尔玛跌0.10%,成交额2796.06万元。两融数据显示,当日德尔玛获融资买入额157....
日常生活中在形容人们仔细听一个... 日常生活中在形容人们仔细听一个声音时常用“侧耳倾听”来形容从物理学的角度来分析,这里面的道理是什么初...
鸡西市副市长批示肯定市邮政管理... 转自:黑龙江省邮政管理局近日,黑龙江省鸡西市副市长高运禄对市行业经济运行情况和下一步工作推进措施作出...
茂莱光学6月6日获融资买入16... 6月6日,茂莱光学跌0.82%,成交额2.06亿元。两融数据显示,当日茂莱光学获融资买入额1651....
马姓股民向*ST锦港发起索赔 ...   受损股民可至Hehson股民维权平台登记该公司维权:http://wq.finance.sina...
诺瓦星云6月6日获融资买入85... 6月6日,诺瓦星云涨1.40%,成交额6688.94万元。两融数据显示,当日诺瓦星云获融资买入额85...
安杰思6月6日获融资买入193... 6月6日,安杰思跌0.33%,成交额2476.57万元。两融数据显示,当日安杰思获融资买入额193....
中电港6月6日获融资买入132... 6月6日,中电港跌0.44%,成交额1.56亿元。两融数据显示,当日中电港获融资买入额1323.00...
阿特斯6月6日获融资买入642... 6月6日,阿特斯跌0.45%,成交额8164.22万元。两融数据显示,当日阿特斯获融资买入额642....
华原股份6月6日获融资买入11... 6月6日,华原股份跌0.06%,成交额3182.07万元。两融数据显示,当日华原股份获融资买入额11...
润本股份6月6日获融资买入15... 6月6日,润本股份跌4.74%,成交额2.81亿元。两融数据显示,当日润本股份获融资买入额1552....