Detours - 挂钩类成员函数 - 设置目标函数偏移的语法?

Posted

技术标签:

【中文标题】Detours - 挂钩类成员函数 - 设置目标函数偏移的语法?【英文标题】:Detours - Hooking a Classes Member Function - Syntax for setting function offset of target? 【发布时间】:2012-05-11 22:19:19 【问题描述】:

对于非类函数 - 我可以简单地声明要绕行的函数的偏移量,例如:

typedef int (_cdecl* SomeFunc)(char* pBuffer, int size);

SomeFunc Real_SomeFunc = (SomeFunc)(0xCAFEBABE);

...

DetourAttach(&(PVOID&)Real_SomeFunc, (PVOID)Hook_SomeFunc); 

现在,绕行类的成员函数会变得很困难 - detours 有一个示例:

https://github.com/microsoft/Detours/blob/master/samples/member/member.cpp

该示例已经定义了目标成员函数 - 但我不只知道将我的 DLL 注入的二进制文件中的偏移量 - 那么我该如何转换它

void (CDetour::* CDetour::Real_Target)(void) = 
    (void (CDetour::*)(void))&CMember::Target;

到这样的事情:

void (CDetour::* CDetour::Real_Target)(void) = 
    (void (CDetour::*)(void))0xCAFEBABE;

这里出现编译错误

有什么提示吗?

【问题讨论】:

【参考方案1】:
void (CDetour::* CDetour::Real_Target)(void) = (void (CDetour::*)(void))0xCAFEBABE;

这里出现编译错误

具体来说,它是error C2440: 'type cast' : cannot convert from 'unsigned int' to 'void (__thiscall CDetour::* )(void). There are no conversions from integral values to pointer-to-member values。转换为成员指针是一件不平凡的事情——它们可能是也可能不是简单的内存地址,具体取决于成员函数的类型和类层次结构的复杂性。多重虚拟继承给这个伪数据结构增加了额外的字段;除了代码地址之外,还有重新定位信息。此数据的格式是特定于编译器的。

出于我的目的,我使用这个特定于 MSVC 的宏:

/// Void pointer to Func pointer.
/// Assumes first four bytes should hold the address and rest be zero.
template<typename T> T VTOF(void* ptr)
// fills in 4 bytes and zeroes the rest
    T result = 0;
    *(void**)&result = ptr;
    return result;

用法:ptr = VTOF&lt;void (CDetour::*)(void)&gt;((void*)0xCAFEBABE); 现在,这显然不适用于真正的复杂代码,但我认为它足以在挂钩中调用原始代码。自从我不得不在成员函数指针上使用它已经有一段时间了。

【讨论】:

以上是关于Detours - 挂钩类成员函数 - 设置目标函数偏移的语法?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Detours 不能再在 Windows 7+ 中挂钩 shell32.dll 函数

detours hooked CreateFile 函数触发堆栈溢出

验证函子的目标对象

使用 Detours 挂钩 Api 在 Detach 上崩溃

Detours Hook:GetVolumeInformation 随机卷序列

可以使用 Microsoft Detours 来挂钩系统范围的调用而不注入每个 proc 吗?