Hooking GetProcAddress crashes (eventually...)

May 1, 2009 at 10:04 AM
Not sure if this is a problem in the hook code, the DllImport or caused by some other outside factor I can't conceive of.

Here's my hook structures:

        #region GetProcAddress

        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        delegate IntPtr DGetProcAddress(
            IntPtr hModule,
            string procedureName);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetProcAddress(
            IntPtr hModule, 
            string procedureName);

        static IntPtr GetProcAddress_Hooked(
            IntPtr hModule,
            string procedureName)
        {
            if (!string.IsNullOrEmpty(procedureName))
            {
                System.Diagnostics.Debug.WriteLine(string.Format("GetProcAddress: \t{0}", procedureName));
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("GetProcAddress: \t(null)");
            }
            return GetProcAddress(hModule, procedureName);
        }

        #endregion

Here's the actual hook:
            try
            {
                GetProcAddressHook = LocalHook.Create(
                LocalHook.GetProcAddress("kernel32.dll", "GetProcAddress"),
                new DGetProcAddress(GetProcAddress_Hooked),
                this);
                GetProcAddressHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
            }
            catch (Exception e)
            {
                Interface.ReportException(e);
            }

I've placed this into FileMon, and run explorer.exe as a target. It will eventually blow up. A few "GetProcAddress:" will make it into dbgview, but it crashes shortly after.

Because it works initially and then stops working with a crash, I assume i'm some how corrupting the stack. Either the DllImport is slightly off (however this is what EasyHook uses in NativeAPI ) or it's something sinister I can't fathom.

Any suggestions?

May 1, 2009 at 11:34 PM
Edited May 2, 2009 at 12:08 AM
So I've about given up on making this stable. But I no longer need GetProcAddress. Let me explain my goal first.

I'm hooking into a game that's launched from a launcher:
Launcher.exe -> Game.exe

This part is easy. I just hook CreateProcess and use CreateAndInject instead of it's own CreateProcess. This works well.

The next thing I need to hook is from DINPUT8.dll. This library is not in the IAT for "Game.exe". Instead, the game has a "GameMiddleware.dll" which in turn has IAT entries for DINPUT.8.dll and the functions I want.

So my hook chain from start to target is this:

Launcher.exe->(CreateProcess)->Game.exe->(LoadLibraryA)->GameMiddleware.dll->(LoadLibraryW)->DINPUT8.dll

Now I have hook LoadLibrary and capture the call that loads "GameMiddleware.dll'.But once I have that hModule, I'm at a lost.

My first attempt was to hook GameMiddleware.dll's LoadLibraryA call. So, when my original hooks in Game.exe detect LoadLibrary on GameMiddleware.dll I took the returning hModule and tried to use it to patch that GameMiddleWare.dll->Kernerl32.dll->LoadLibraryA() address. 

I did the following:

        /// <summary>
        /// Give us a chance to hook an imported dyanmic library
        /// </summary>
        /// <param name="hModule"></param>
        /// <param name="libraryName"></param>
        public void HookModule(IntPtr hModule, string libraryName)
        {
            // We only get called on newly loaded libraries. If it's already been loaded we're not called. so no need to track
            //TODO: For complete coverage, we need to hook LoadLibrary (A/W) and LoadLibraryEx (A/W)

            this.WriteMessage("\t\tHookModule: {0}", libraryName);

            StringBuilder strFullPath = new StringBuilder(256);
            GetModuleFileName( hModule.ToInt32() , strFullPath, strFullPath.Capacity);
            this.WriteMessage("\t\tFull Path: {0}", strFullPath);

            IntPtr Method = IntPtr.Zero;
            string procName = string.Empty;
            try
            {
                procName="LoadLibraryA";
                Method = NativeAPI.GetProcAddress( hModule, procName );
                
                if (Method == IntPtr.Zero )
                {
                    this.WriteMessage("\t\t\tCould not find Procedure '{0}' in hModule: {1}", procName, hModule.ToString());
                } else {
                    this.WriteMessage("\t\t\tLoadLibrary ( on library ) hooking...");
                    LoadLibraryHook = LocalHook.Create(
                    Method,
                    new DLoadLibrary(LoadLibrary_Hooked),
                    this);
                    LoadLibraryHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
                }
            }
            catch (Exception e)
            {
                Interface.ReportError(RemoteHooking.GetCurrentProcessId(), e);
            }
        }

This fails to find the LoadLibraryA in GameMiddleWare.dll, even though I can see it with the PE Viewer. I thought since I have the hModule of GameMiddleWare.dll I could simply call GetProcAddress using it and "LoadLibraryA" and wal'la, I have a function pointer to hook. Apparently not.

I found this article http://www.codeguru.com/cpp/w-p/dll/hooking/article.php/c3639  in which someone takes the original APIHijack code and makes it do exactly what I want. But I have no idea how EasyHook deals with IAT/PIMAGE_IMPORT_DESCRIPTOR etc... ( and I'd rather not ).

So that's my story. Anyone have any suggestions? Any way to make this work using EasyHook w/o having to change the way EasyHook works?

Thanks for any thoughts...


** Edit:
I just had a thought. Perhaps for this to work, I need to compute the Method pointer myself. I'll need to add the loaded module's offset + the stub to the imported function. Then hook the resulting pointer.

So, Game.exe would be the start + Offset to where GameMiddleware.dll was loaded into game.exe's PE image + the offset to the IAT stub function for the module/function I want that GameMiddleware.dll uses.

So I guess I have to be able to read the PE image info and get some numbers out of the IAT to hook grandchildren modules?