hook虚表,快速获取怪物动向,boss技能

有同学问我什么是虚表hook,是不是很难? 其实相较于其他hook,虚表hook是最简单的.

我们先来复习下什么是虚函数.

虚函数是指父类中被声明, 子类中被重新定义的成员函数.

当类有虚函数的时候,会自动产生虚表.

比如这个人物对象下, 前8字节就是虚表地址(32位的话是4字节续表地址), 后面就是对象的属性.

hook虚表,快速获取怪物动向,boss技能_第1张图片

游戏中的类继承关系极为复杂,重写的函数也特别多,所以基本上都是有虚表的.

虚函数被调用的时候是这样的流程

hook虚表,快速获取怪物动向,boss技能_第2张图片

首先rcx是对象

通过mov rax,[rcx] 就得到了虚表地址

虚表地址+偏移里的值 可以得到其中某个虚函数的地址 这里是[rax+C08],对应的是走路,如下图,7FF8CD2AC46D就是走路函数地址

然后直接  call [rax+C08] 即可

hook虚表,快速获取怪物动向,boss技能_第3张图片

如果把这个地址修改了他是不是就可以执行其他的函数了,甚至是我们自己写的函数.

下载xdbg等工具可以公众号 任鸟飞逆向.

那么了解了这个调用过程,和修改的基本思路,我们就可以对他进行hook了.

原理非常简单:

虚函数地址是通过虚表中获得的,

那么我们把虚表中的虚函数地址修改成我们自己的函数地址,

这样虚函数调用的时候就会调用到我们的函数了.

同时,为了不影响他原来的功能,

执行完我们的代码,我们再调用他原来的真正的虚函数即可.

那么可以上代码了:

void Ctextdialog::OnBnClickedButton14()
{
    
    hookVirtualTable(*(uintptr_t*)Base_人物, 0xC08);

}


void Ctextdialog::OnBnClickedButton15()
{
    uhookVirtualTable(*(uintptr_t*)Base_人物, 0xC08);

}
uintptr_t oldVirtualTable = 0;
void hookVirtualTFunc(uintptr_t RCX,uintptr_t RDX,uintptr_t R8,uintptr_t R9,uintptr_t arg5,uintptr_t arg6)
{
    if (R8 == 1)
        printf_rnf("人物跑: %.0f,%.0f,%.0f", *(FLOAT*)RDX, *(FLOAT*)(RDX+4), *(FLOAT*)(RDX+8));
    else
        printf_rnf("人物走: %.0f,%.0f,%.0f", *(FLOAT*)RDX, *(FLOAT*)(RDX + 4), *(FLOAT*)(RDX + 8));

    Call(oldVirtualTable, RCX, RDX, R8, R9, arg5, arg6);//调用原来的虚函数  不影响他原来的代码    
}

void hookVirtualTable(uintptr_t obj, uintptr_t offset)
{
    uintptr_t virtualTable = *(uintptr_t*)obj;// 第一步先获得虚表
    oldVirtualTable = *(uintptr_t*)(virtualTable + offset);//第二步保存原来的虚函数地址
    DWORD old = 0;
    VirtualProtect(PVOID(virtualTable + offset), 0x100, PAGE_EXECUTE_READWRITE, &old);
    *(uintptr_t*)(virtualTable + offset) = (uintptr_t)hookVirtualTFunc;//第三步把虚函数地址写成我们自己的函数地址
    VirtualProtect(PVOID(virtualTable + offset),0x100, old,&old);
}

void uhookVirtualTable(uintptr_t obj, uintptr_t offset)
{
    uintptr_t virtualTable = *(uintptr_t*)obj;//第一步获得虚表
    DWORD old = 0;
    VirtualProtect(PVOID(virtualTable + offset), 0x100, PAGE_EXECUTE_READWRITE, &old);
    *(uintptr_t*)(virtualTable + offset) = oldVirtualTable;//第二步 把原来虚函数地址 写回去
    VirtualProtect(PVOID(virtualTable + offset), 0x100, old, &old);
}

这样就对走路功能进行了时时hook

拓展题目:

我们怎么快速获得 每个怪物的下一步动向?比如BOSS技能?

可以给老师留言你的答案.

你可能感兴趣的:(游戏安全,C++,游戏安全,逆向,封包,协议)