Solved

Hooking delay loaded DLLs?

Posted on 2010-11-21
19
1,492 Views
Last Modified: 2013-12-03
Hi,

What is the 'correct' way to hook functions which are in DLL's loaded /after/ I've injected my own (MFC) API-hooking DLL?  I have some processes I'm trying to hook whose libraries I am interested in are sometimes loaded after I've attempted the hook, so the hook is missed.  Is there a reliable way to ensure functions I am interested in are hooked as soon as they are loaded i a DLL?

Thanks,
Chris J
0
Comment
Question by:chrispauljarram
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 9
19 Comments
 
LVL 5

Expert Comment

by:greatsubash
ID: 34185874
0
 

Author Comment

by:chrispauljarram
ID: 34186742
Hi greatsubasg,

I've had a quick look at those but can't see anything there that refers to my actual problem?  They seem to just give advice about hooking methods and not detecting when DLL's are delay loaded in order to not miss the opportunity to patch their IAT entries at that time..

Apologies if I'm misexplaining, I hope this clarifies things a little.

Thanks,
Chris
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34186754
In this case, you need to hook LoadLibrary, so when a new DLL is loaded, you can look to see if it is one you are interested in.  If it is, then you can inject your hooking stuff into the DLL, otherwise ignore it.

HTH
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:chrispauljarram
ID: 34186770
OK I'll give that a go today, I was aware of that method and did wonder if maybe that was the correct way to do it (i.e. It'll work in all cases) but wanted to hear it from the horses mouth :)  Will try it out and report back in a bit.

Cheers,
Chris
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34186780
Yeah, it is the way to go.  If you get hold of the Jeffrey Richter's book about hooking, he talks a lot about it, with some cool example code.  Be aware though that hooking is a *very* dangerous game and it may lead to no end of problems, including system wide crashes (I know, I have been there :)).  I have written classes that help with it all though, so if you ever need any help in general, let us know :)
0
 

Author Comment

by:chrispauljarram
ID: 34190481
Hi again mywad99,

I'll try and get hold of a copy of Jeffrey's book, sounds like it could be very useful.  Yes I would be /extremely/ grateful if you have any classes I can look at that help with this!  I tried patching LoadLibrary and hit a few problems.

Firstly, am I right in saying I need to attempt to hook all of the following?:-

LoadLibrary
LoadLibraryA
LoadLibraryW
LoadLibraryEx

(are there any others I'm missing?)

Reason I ask is the first app I injected only uses LoadLibraryA from Kernel32.dll (according to dependency walker).

The second problem is the instant I try and hook LoadLibraryA, it closes the app I am trying to hook -  Could this be because I'm attempting the IAT patch from within my 'InitInstance' MFC DLL function, the one called in my injected DLL to inject it in the first place?  Just wondering what the safe way to do this is...  I think ultimately I'll move this all to a standard Win32 dll to ditch the MFC dependency completely, but not sure that would solve this problem?

Thanks again, your help is very much appreciated!

Chris
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34191493
Take a look at the class I wrote for hooking, hopefully it will help you.  Any questions please ask...

 APIFunctionHooker.h APIFunctionHooker.cpp
0
 

Author Comment

by:chrispauljarram
ID: 34192248
Hi again,

Well by strange coincidence that is already the exact class I'm using already!  Don't recall seeing an author name on it, guess maybe I grabbed it from another thread here some time ago?  What it does mean though at least is you are the best person to help with it!  I'm trying to patch LoadLibraryA in my InitInstance function using:-

CFuncInAPIHook::Instance().HookFunction ( _T("kernel32.dll"), _T("LoadLibraryA"), AfxGetInstanceHandle(), ( PROC )&myLoadLibraryA );

All other functions patch 100% fine using this call (many OpenGL calls I'm patching for instance), but trying to patch loadlibrary like this closes the target app.

Any ideas?

Cheers once again, and thanks for the use of your library btw :)

Chris
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34195883
Heh, I had a feeling I had given that class to someone on here before, just did not remember it was you!

Can you upload a simple cut down version of your app (say, an MFC dialog app) that demonstrates this issue please?  Or just paste the entire .cpp that contains your calls, so I can step through it and help figure out the problem?

TIA
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34195935
Whilst you upload that, some food for thought: I am not sure that LoadLibrary will be called if you are delay loading a DLL; according to http://msdn.microsoft.com/en-us/library/151kt790.aspx it "relieves you of the need to use the Windows SDK functions LoadLibrary and GetProcAddress to implement DLL delayed loading"

Hmm.....
0
 

Author Comment

by:chrispauljarram
ID: 34205344
Hi again,

Sorry for the delay, got called away yesterday.  I've just put together the most basic of MFC DLL's which does nothing but try and hook LoadLibraryA using your APIHooking classes.  Of the two games I've injected this into (it gets injected automatcially by another app when the game process is detected, just using the bog standard CreateRemoteThread / LoadLibrary technique), they both crash on startup ("xxx has stopped working..."). /However/, prior to crashing there are a few calls to my version of LoadLibrary that are working (and printing out the parameter correctly), so it appears to be working initially but the hook is then causing a crash after a few LoadLibrary calls.  I've attached the project (it is a .rar file with a .zip extension to force the attachment system to accept it), one example game where this happens if you want to try and inject into it is the demo release of NoLimits rollercoaster simulator, it is very small, quick to run and downloadable at http://www.nolimitscoaster.com/Download/download.html.

Thanks again, I hope this is something simple :)

Cheers,
Chris
TelemReader.zip
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34207113
OK.  It would be good to see exactly how you are injecting this: can you post the code you are using that injects this simple DLL please, explaining how you acquire the handle to the process for injection?  Not being dumb here, it might be that the principle is sound but you are making a mistake early on in the process.  

Ideally, I need some code that run "out of the  box" if you get me, without having to spend time setting up the problem where that time would be better spent helping you solve the problem!
0
 

Author Comment

by:chrispauljarram
ID: 34207415
OK, well the DLL is definately being injected lets put it that way.. it is running and printing debug output to a console.  The process handle (which is valid and being used elsewhere in the application ) is obtained using:-
m_hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_CREATE_THREAD|
                    PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, processID);

The only thing not working is the LoadLibrary hooking.  I know this same function is being used to inject the code in the first place, but afaik this shouldn't interfere with its patching?


The section of injection code is:-

      m_hLibModule = 0;
      CString pluginName = CString(CGlobals::m_strWorkingDirectory) + "\\" + TELEM_READER_PLUGIN_NAME + "\0";
      char szLibPath[_MAX_PATH];
      memcpy(szLibPath, pluginName.GetBuffer(), pluginName.GetLength() + 1);
      LPVOID remoteAddress = VirtualAllocEx(m_hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE);

      if(remoteAddress != NULL)
      {
            if(WriteProcessMemory(m_hProcess,remoteAddress,(void*) szLibPath,sizeof(szLibPath),NULL) != 0)
            {
                  HMODULE hModule = GetModuleHandle((LPCSTR) "Kernel32");
                  FARPROC pa = GetProcAddress(hModule, "LoadLibraryA");
                  HANDLE rt = CreateRemoteThread(m_hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pa, remoteAddress, 0, NULL);

                  if(rt != NULL)
                  {
                        WaitForSingleObject(rt, INFINITE);
                        GetExitCodeThread(rt, &m_hLibModule); // get remote module address for unloading when this process is closed.

                        if(m_hLibModule == 0)
                        {
                              // Report injection error.
                        }
                        else
                        {
                              // Report injection success.
                        }
                  }
            }
            
            VirtualFreeEx(m_hProcess, remoteAddress, 0, MEM_RELEASE);
      }

Building the DLL project I sent you and changing the plugin name above should hopefully be enough for this to work (assuming you have the ID of the process to test with)...

Cheers,
Chris
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34209275
This is very interesting, and I will adhere to help you find a solution to your problem.  I am trying to replicate the problem at the minute, and as soon as I can do that I will be back (bear in mind this might not be until the weekend now, sorry - lots to do (to get paid for :))

What I would advise though is what I was trying do do: write two simple apps: one that has your injection code above and one that dynamically loads, via LoadLibrary, a DLL written by you (the simple Win32 DLL with Export Symbols option in VS is enough).  Have the injection app inject your telemReader dll into the the second executable, then have that executable call LoadLibrary (via a button click handler, say).  Then see if you get the same hanging problem.
0
 

Author Comment

by:chrispauljarram
ID: 34209925
Cheers again my friend :)  Its not super-urgent so no probs for the delay, just appreciate the help - To look at it from a different perspective (and taking into account what you say about loadlibrary not necessarily being called for delay-loaded modules) I'm just wondering if it would be better to periodically enumerate the modules of the target process every second or so (from my injecting app) until those I'm interested in are present, and do the injection / hooking then - do you think this makes more sense?

Thanks,
Chris
0
 
LVL 19

Accepted Solution

by:
mrwad99 earned 500 total points
ID: 34259178
Have not forgotten about this btw, still fiddling with it when I get the time.  Have also commented on your other question, which might be of use...
0
 

Author Comment

by:chrispauljarram
ID: 34278769
Not to worry with this one, I'm just checking for the module's presence in a loop now (using GetModuleHandle(name)) until it is present.

Cheers,
Chris
0
 

Author Closing Comment

by:chrispauljarram
ID: 34278773
Partial solution, thanks again :)
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 34291487
No problem :o)  Like I say, I will investigate whether or not LoadLibrary gets called when a delay loaded DLL is loaded: if not, it looks like you have the solution with your loop as you described above.
0

Featured Post

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question