如何获取指向 COM 方法的指针以进行挂钩?
我知道这似乎是一个被过度回答的问题,但这个问题有所不同。 我有这个 ActiveX 对象,它导出一些方法。我需要在其方法之一上设置一个钩子,即 Func1
,我知道如何使用 VirtualProtect()
等来做到这一点。如果我打开 ollydbg 并深入研究在 ActiveX DLL 中,我准确地看到了需要设置挂钩的 Func1
的地址。
使用 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]
且具有相同接口 ID 的 Func1
ptr。永远。正确的?
我可能会用伪代码做这样的事情:
#define FUNC1_ENTRY 0x1C / sizeof(LPBYTE)
CoCreateInstance(CLSID_MyActx, 0, CLSCTX_ALL, IID_IMyActxObj, (LPVOID*) &pObj);
LPVOID pToHook = (*pObj)[FUNC1_ENTRY];
I know this seems like a over-answered question but this one is different.
I have this ActiveX object which exports some methods. I need to set a hook on one of its methods, namely Func1
, I know how to do this by using VirtualProtect()
, etc. If I open ollydbg and dig into the ActiveX DLL I see exactly the address of the Func1
where I need to set the hook.
Using Visual Studio 2008, I am using the precompiler directive:
#import "myactx.dll" no_namespace, named_guids, raw_interfaces_only
And in my code I am trying to do this:
LPVOID ptr = &IMyActx::Func1;
which returns an error when compiling:
error C2440: 'initializing' : cannot convert from 'HRESULT (__stdcall IMyActx::* )(BSTR,BSTR)' to 'LPVOID'.
I researched and found that I can't cast a pointer-to-class-method to a pointer-to-function because of the implicit this
param.
However, I don't intend to call this function. I just want to know its address in memory so that I can pass it to my hooking routine (which expects a LPVOID
pointer).
This seems inconceivable to me that I can call a function but not get its raw address in memory. It makes me want to insert some x86 assembly code just to get the pointer I want.
Any suggestion is greatly appreciated, thanks for reading.
EDIT...
Now thinking of it... LPVOID ptr = &IMyActx::Func1;
should not work because IMyActx
is a pure virtual class! Anyway I tried some combinations before of instantiating an object and trying to get the raw pointer to Func1
but nothing worked so far. I see in ollydbg that a call to Func1
is generated as:
mov edx, [eax];
call dword ptr ds:[edx + 0x1C];
So I can assume I need to read the DWORD
at vptr + 0x1C
bytes and voilá.
If I recall correctly, the Component Object Model guarantees that it will always be the Func1
ptr laying at [vptr + 0x1C]
given the same Interface ID. forever. Right?
I will probably do something like this, in somewhat pseudo-code:
#define FUNC1_ENTRY 0x1C / sizeof(LPBYTE)
CoCreateInstance(CLSID_MyActx, 0, CLSCTX_ALL, IID_IMyActxObj, (LPVOID*) &pObj);
LPVOID pToHook = (*pObj)[FUNC1_ENTRY];
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
COM对象的方法实际上是普通的函数。这就是使 COM 客户端能够用 C 而不是 C++ 编写的原因。
我建议为 C 客户端生成头文件,然后可以轻松检索函数地址。但是,您首先需要一个要挂钩的类的实例。
Methods of COM objects actually are ordinary functions. That's what enables COM clients written in C instead of C++.
I recommend generating the header file for a C client, the function address will then be easily retrieved. You do first need an instance of the class you intend to hook, however.
如果我理解正确的话,您想将指向类方法的指针转换为函数指针。
这实际上是不可能的。
简单的例子:
你甚至不能使用
reinterpret_cast
。曾经也遇到过这个问题。然后我只需创建一个函数,将输入值映射到指向对象的指针。也许您可以创建一个包装函数,在其中通过指向该方法的指针来调用该方法?
If I understand you correctly, you want to cast a pointer to a class method into a function pointer.
This actually is not possible.
Simple example:
You cannot even use
reinterpret_cast
.Had this problem once, too. Then I simply had to create a function that maps the input value to a pointer to the object. Maybe you could create a wrapper function in which you call the method by having a pointer to it?