Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a pointer to a COM method for hooking?

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];
like image 726
Marcus Geist Avatar asked Aug 22 '26 02:08

Marcus Geist


1 Answers

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.

like image 56
Ben Voigt Avatar answered Aug 24 '26 16:08

Ben Voigt