Hooking C++ member function

c++ / delphi package - dll injection and api hooking
Post Reply
wrolm
Posts: 1
Joined: Sun May 23, 2004 4:27 pm

Hooking C++ member function

Post by wrolm »

I am trying to hook a C++ member function of a dll and am having some problems. The exported function name is decorated -

Code: Select all

?Log@Output@@QAAXPBGZZ
The undecorated function looks like -

Code: Select all

 void __cdecl Output::Log(unsigned short const*,...) 
Will I be able to use madCodeHook for this? Thanks!
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

It should be possible to hook that function, but you must make sure that both your hook callback function and the next-function-variable have exactly the same parameters and calling convention as the to-be-hooked function. They also need to be part of a class, because the to-be-hooked function is also part of a class.
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

i'm having a similar problem

it just seems i can't seem to get a pointer to a function from a nonstatic method of a class instance i.e

PVOID mypvoid = (PVOID) myclassinstance.mymethod;
just doesn't work
neither does
PVOID mypvoid = (PVOID) &myclassinstance.mymethod;

any clues from this, from reading C++ forums there seems to be alot of controvesy of function pointers to methods.. with C++ internally sending 'this' as the first parameter.. but there surely must be a way.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Let's say you want to hook this one:

integer SomeClass.SomeMethod(integer param1, LPTSTR param2)

You have to do this, I think:

integer (*SomeClassSomeMethodNext) (PVOID self, integer param1, LPTSTR param2);

integer SomeClassSomeMethodCallback(PVOID self, integer param1, LPTSTR param2)

See? You need to add the hidden first "self" parameter to the list of arguments to both the "NextHook" function variable and to your hook callback function.

But this might depend on the calling convention which the method uses. Maybe this works only for WINAPI/STDCALL? I'm not sure...
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

i see that - looks like a useful technique
my main question is how do i get a pointer to the address of the C++ method?
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Well, in Delphi you can simply do "@TSomeClass.SomeMethod". Unfortunately I don't know how it works in C++, I'm sorry.
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

yeah in C++, method pointers (in contrast to function pointers), aren't 4 bytes, but sometimes 8 or 12 bytes long, and seem to be quite weird, containing a pointer to the virtualmethod table, and also the offsets or something, but i'm sure there must be a way we can wrap up this functionality somehow.
:cry:
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

I'm no C++ expert. In Delphi methods are always 8 bytes long, but when using @ you really get only 4 bytes. I guess you have to ask this on a C++ forum, I really have no clue here...
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

man i love dephi, i wish this project i am working on now was in delphi :)
on the delphi front hooking "@TSomeClass.SomeMethod"
would hook every call that that method of every instance right?

as for C++,
i'm working on a framework now to do it, (we can already do it for static methods), but i'm using inline assembler to do the equivilent of "@TSomeClass.SomeMethod" since C++ compiler doesn't let such a thing to do done..
its working our well, other than you can't make a function with the same calling convetion of nonstatic methods (THISCALL calling convention(which is basically like STDCALL, but with pointer to the class instance (this) is passed in ECX register) in C, other than inside classes, so my hooked functions will also have to have at least ASM prolog and epilog headers to deal with the parameter calling, so thinking of the best way to make a generic solution for this at the moment.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

klumsy wrote:man i love dephi
Me, too!
klumsy wrote:on the delphi front hooking "@TSomeClass.SomeMethod" would hook every call that that method of every instance right?
Yes.
klumsy wrote:as for C++, i'm working on a framework now to do it, (we can already do it for static methods), but i'm using inline assembler to do the equivilent of "@TSomeClass.SomeMethod" since C++ compiler doesn't let such a thing to do done..
its working our well, other than you can't make a function with the same calling convetion of nonstatic methods (THISCALL calling convention(which is basically like STDCALL, but with pointer to the class instance (this) is passed in ECX register) in C, other than inside classes, so my hooked functions will also have to have at least ASM prolog and epilog headers to deal with the parameter calling, so thinking of the best way to make a generic solution for this at the moment.
Sounds interesting. Would you mind posting here if you find a working solution?
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

i noticed 2 things..
madcodehook doesn't work (doesn't successfully hook) with debug builds (whether plain C functions, static methods, non static methods, or virtual(and non static) methods in msvc++ 7.

i have the solution working for non static methods, but can't yet hook virtual ones (i can ge tthe pointers, but madecodehook doesn't hook it, probably because of one of those safety reasons (functions have a jump right away due to nature of the 'vcall' virtual call.
klumsy
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm
Contact:

Post by klumsy »

ok here are some snippets

Code: Select all

PVOID doitptr;
PVOID hookdoitptr;
PVOID NextHook;
...
//declaration of method function that will be hooked
long Test::DoIt(long x)
{
...
}

//code to get pointers needed for hooking
_asm {
           mov eax,DWORD PTR Test::DoIt;
           mov doitptr,eax	 
          }
_asm {
           mov eax,DWORD PTR TestHook::HookDoIt;
           mov hookdoitptr,eax	 
          }
//install the hook
if (!HookCode(doitptr, hookdoitptr, (PVOID*) &NextHook))
		MessageBox("did not hook right");
//until it is unhooked whenever Test::Doit is called, TestHook::HookDoIt will be called
instead.

..
//and actually what does TestHook::HookDoIt contains?

long TestHook::HookDoIt(long x)
{
	long retvalue;
	Test * testptr = (Test *) this;
	//now do whatever we want here
	CString tmpstr;
	tmpstr.Format("inside the hook x: %d this.z : %d",x,testptr->z);
	MessageBox(0,tmpstr,"",0);
	//now we are done, call the original simulating thiscall calling technique
	_asm {
		push x
		mov ecx,this
		call NextHook;
		mov retvalue,eax		 
	}
   return retvalue;
};
...
//and we might want to uninstall the hook sometime
UnhookCode((PVOID*) &NextHook);
the most difficult thing is calling the original method, since there is no way in C,C++ to call thiscall otherthan through normal C++ method calls.

this call is same as STDCALL other than the pointer to 'this' self reference is put in ecx.. so basically parameters put on the stack backwards and return value in eax
so in this case
_asm {
push x
mov ecx,this
call NextHook;
mov retvalue,eax
}
is just pushing one thing because there is just one parameter

maybe another way we could do this, without having to have the calling nexthook in asm (though we will still need the asm for getting the pointers)
would be to make in TestHook another method called
TestHook::NextHook(long x)
and call that instead of the asm above.
and use madeChook to hook NextHook to call the original method? (and the contents of TestHook::NextHook would not be important for it would never be actually called?

what do you think?
[/code]
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

klumsy wrote:ok here are some snippets
Thanks for the code! Well, in Delphi the "Self" pointer is stored just as any other parameter, so there's no problem.
klumsy wrote:maybe another way we could do this
Hmmmmm... Might be possible, I'm not sure... I'm glad that things are so much easier in Delphi... :D
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

wrolm, have a look here:

viewtopic.php?p=976#976
manutai
Posts: 85
Joined: Sun Aug 03, 2008 1:40 am

Re:

Post by manutai »

madshi wrote:It should be possible to hook that function, but you must make sure that both your hook callback function and the next-function-variable have exactly the same parameters and calling convention as the to-be-hooked function. They also need to be part of a class, because the to-be-hooked function is also part of a class.

Can you Provide or point out a sample for the same?
Post Reply