【发布时间】:2011-04-04 18:38:08
【问题描述】:
我知道这似乎是一个过度回答的问题,但这个问题不同。
我有这个导出一些方法的 ActiveX 对象。我需要在它的一种方法上设置一个钩子,即Func1,我知道如何使用VirtualProtect() 等来做到这一点。如果我打开ollydbg 并深入研究ActiveX DLL,我会看到@987654323 的地址@ 我需要设置钩子的地方。
使用 Visual Studio 2008,我正在使用预编译器指令:
#import "myactx.dll" no_namespace, named_guids, raw_interfaces_only
在我的代码中,我正在尝试这样做:
LPVOID ptr = &IMyActx::Func1;
编译时返回错误:
错误 C2440:“正在初始化”:无法从“HRESULT (__stdcall IMyActx::*)(BSTR,BSTR)”转换为“LPVOID”。
我研究并发现由于隐含的 this 参数,我无法将指向类方法的指针转换为指向函数的指针。
但是,我不打算调用这个函数。我只想知道它在内存中的地址,以便我可以将它传递给我的挂钩例程(它需要一个 LPVOID 指针)。
这对我来说似乎不可思议,我可以调用一个函数但不能在内存中获取它的原始地址。这让我想插入一些 x86 汇编代码只是为了得到我想要的指针。
非常感谢您的任何建议,感谢阅读。
编辑...
现在想起来了……LPVOID ptr = &IMyActx::Func1; 不应该工作,因为IMyActx 是一个纯虚拟类!无论如何,我在实例化一个对象之前尝试了一些组合并尝试获取指向Func1 的原始指针,但到目前为止没有任何效果。我在 ollydbg 中看到对Func1 的调用生成为:
mov edx, [eax];
call dword ptr ds:[edx + 0x1C];
所以我可以假设我需要在vptr + 0x1C 字节处读取DWORD,然后瞧。
如果我没记错的话,组件对象模型保证它总是位于[vptr + 0x1C] 的Func1 ptr 给定相同的接口ID。永远。对吧?
我可能会用一些伪代码来做这样的事情:
#define FUNC1_ENTRY 0x1C / sizeof(LPBYTE)
CoCreateInstance(CLSID_MyActx, 0, CLSCTX_ALL, IID_IMyActxObj, (LPVOID*) &pObj);
LPVOID pToHook = (*pObj)[FUNC1_ENTRY];
【问题讨论】:
-
指向方法的指针和指向函数的指针不可转换,因为标准不保证(故意)方法指针可以存储在 void* 中。而一个简单的函数指针可以存储在一个 void* 中。
-
@Martin reinterpret_cast 编译时返回:
code错误 C2440:'reinterpret_cast':无法从 'HRESULT (__stdcall IMyActx::* )(BSTR,BSTR)' 转换为 'LPVOID' 1>没有可以进行这种转换的上下文code -
抱歉,这是一时冲动,虽然我认为是错误的。我把它拿出来是因为它不应该工作。 (注意方法指针可能比普通指针大。所以它不能转换成 void*)。
-
问题不仅在于指针大小,还在于ptm性质。如果它指向抽象类的虚拟方法,并且仅在您提供此方法时才调用分派;)?指向成员的指针根本不是“真正的”内存指针......
-
您在 update 中描述的解决方案应该可以工作,但看起来很危险 :) 几年前,我使用绕道来连接 activex 对象。我刚刚使用了 ANSI C 版本的 activex 接口(你知道,midl 在一个文件中生成两个版本,一个用于 C,一个用于 C++)。
标签: c++ winapi assembly activex member-function-pointers