Hooking C++ member function

c++ / delphi package - dll injection and api hooking

Hooking C++ member function

Postby wrolm » Sun May 23, 2004 4:44 pm

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!
wrolm
 
Posts: 1
Joined: Sun May 23, 2004 4:27 pm

Postby madshi » Sun May 23, 2004 7:54 pm

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.
madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby klumsy » Tue Jul 27, 2004 2:06 pm

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.
klumsy
 
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm

Postby madshi » Wed Jul 28, 2004 7:04 am

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...
madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby klumsy » Sat Jul 31, 2004 12:48 pm

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?
klumsy
 
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm

Postby madshi » Sat Jul 31, 2004 1:05 pm

Well, in Delphi you can simply do "@TSomeClass.SomeMethod". Unfortunately I don't know how it works in C++, I'm sorry.
madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby klumsy » Thu Aug 05, 2004 2:53 am

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:
klumsy
 
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm

Postby madshi » Thu Aug 05, 2004 6:30 am

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...
madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby klumsy » Fri Aug 06, 2004 4:30 am

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.
klumsy
 
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm

Postby madshi » Fri Aug 06, 2004 6:58 am

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?
madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby klumsy » Fri Aug 06, 2004 8:18 am

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

Postby klumsy » Fri Aug 06, 2004 11:07 pm

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]
klumsy
 
Posts: 9
Joined: Tue Jul 27, 2004 2:03 pm

Postby madshi » Sat Aug 07, 2004 7:05 am

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: 9704
Joined: Sun Mar 21, 2004 5:25 pm

Postby madshi » Tue Aug 10, 2004 7:02 am

madshi
Site Admin
 
Posts: 9704
Joined: Sun Mar 21, 2004 5:25 pm


Return to madCodeHook

Who is online

Users browsing this forum: No registered users and 1 guest