How to hook a method from ANY thread in the process (unmanaged)?

May 30, 2012 at 12:41 AM

I've been having some issues getting my method hooks to work.  I can get the hook to work if "I" call the method that's being hooked.  But when it occurs naturally during the processes operation, it doesn't get hooked.  My problem is probably stemming from the fact that I'm actually setting these hooks in my own thread that I've spawned.  And apparently the LhSetInclusiveACL() method needs to know the thread that you want to hook. Well, here are my issues...

  1. I don't really care which threads apply the hook, i want them all to be hooked.  For example, lets say I want the CreateICW() method from the "gdi32.dll" library hooked for the entire process "iexplorer.exe".  Not just from thread ID number 48291 or whatever.
  2. Knowing which threads are going to be calling the routines you are interested in hooking requries intimate knowledge of internal workings of the process you are hooking.  I'm speculating that is generally not feasable and ceratinly not feasable for me.  Thus its kind of impossible for me to know a priori which thread IDs need to be hooked.

 

The following code was taken from the "UnmanageHook" example.

extern "C" int main(int argc, wchar_t* argv[])
{
    //...
    //...
    //...

    /*
        The following shows how to install and remove local hooks...
    */
    FORCE(LhInstallHook(
            GetProcAddress(hUser32, "MessageBeep"),
            MessageBeepHook,
            (PVOID)0x12345678,
            hHook));

    // won't invoke the hook handler because hooks are inactive after installation
    MessageBeep(123);

    // activate the hook for the current thread
    // This is where I believe my problem is.  ACLEntries is 
    // supposed to have a list of thread IDs that should pay
    // attention to the MessageBeep() hook.  Entries that are
    // "0" get translated to be the "current" threadID.  I want
    // ALL threads and I don't want to have to try to figure out
    // which threads will be spawned in the future for the given
    // process.  The second parameter is InThreadCount. I'm
    // kind of shocked that you can't just pass in 0 or -1 or
    // something for this parameter and just have it hook all
    // threads in that given process.
    FORCE(LhSetInclusiveACL(ACLEntries, 1, hHook));

    // will be redirected into the handler...
    MessageBeep(123);


    //...
    //...
    //...
}

I've added some comments to the LhSetInclusiveACL() method call explaining the situation.  Also LhSetExclusiveACL() and the "global" versions for these methods don't seem to help either.  Am I using this wrong?  I imagine that this is how the majority of implementations would use this library, so why is this not working for me?

Coordinator
May 31, 2012 at 1:01 AM

Yes you can hook all threads, here is how I do it from a managed environment:

myHook.ThreadACL.SetExclusiveACL(new Int32[1]);

I believe doing this without a call to SetInclusiveACL will give you the behaviour you are after.

Yes the documentation requires updating, and tutorials covering more use cases need to be provided. Any help is greatly appreciated in this.

Cheers,

J


May 31, 2012 at 7:55 PM

Interesting.  I actually was thinking about using the SetExclusiveACL() method.  However, it requires you to give it at least one thread ID.  In the back of my head I always wondered, "What if I give it a thread ID, and the process coincidentally creates a thread with that very same ID. If that happened, it would fail and I'd NEVER find out what the problem was."  I do suppose though, i could try giving it a thread ID that is not possible like MAX_INT or something.  If it doesn't puke right away, then it'll never run across a thread with that ID, effectively giving me the behavior i want like you suggest.

Thank you.  I will try this out.