在以下情况下,为什么 vmt 挂钩不能与实例成员一起使用?

逆向工程 函数挂钩 勾搭
2021-06-28 15:31:56

为什么在使用实例成员 obj.myFunc() 调用时函数没有被挂钩?

class Myclass
{

public:
    virtual void myFunc() = 0;

};
class Derived : public Myclass
{
public:
    void myFunc()
    {
        std::cout << "Actual method is called" << std::endl;
    }
};

    void __fastcall hk_myFunc(void* thisPtr, int edx)
    {
        std::cout << "Hooked method is called" << std::endl;
    }

typedef void(__thiscall *fPtr)();

int main()
{
    Derived* ptr = new Derived();
    ptr->myFunc();// Output : Actual method is called.
    void** vTPtr = *(reinterpret_cast<void ***>(ptr));
    DWORD oldProtection;
    VirtualProtect(vTPtr, 4, PAGE_EXECUTE_READWRITE, &oldProtection);
    *vTPtr = reinterpret_cast<fPtr>(&hk_myFunc);
    VirtualProtect(vTPtr, 4, oldProtection, 0);
    ptr->myFunc(); //Output: Hooked method is called
    Derived obj = *ptr;
    obj.myFunc(); // Output : Actual method is called. Why ??
    return 0;
}
1个回答

问题在于您使用新指针引用此对象的方式。

Derived obj = *ptr;

这实际上利用旧对象的数据创建了一个新对象。耶!C++!

IDA反编译

在第 27 行中,您可以看到通过调用构造函数生成了一个新对象。如果您查看反汇编,您会看到 vtable 未用于函数调用。因此,您最终会得到未修改的函数。

拆卸

顺便说一句,当您将上面引用的行更改为

(*ptr).myFunc();

输出按预期工作