5

I have written a C API with support for static import hooking via overwriting the corresponding IAT entry of an exported function. It works nicely for older simple applications, but for more modern applications, it is less effective. This is primarily due to the large amount of applications nowadays that dynamically import functions.

My solution to this problem was to create the process in an initial suspended state and then hook the LoadLibrary(Ex)(A/W) family of functions along with GetProcAddress() to replace the retrieved address of a target function with my own. That solution is limited in part due to the fact that it is based off the application only importing dynamic functions and libraries in the executable module, without working for processes created later ( although that could be solved by hooking CreateProcess() ) or more importantly, it doesn't handle the DLLs in the application that also call the target functions I want to hook. This is obviously because the DLLs have a separate import section in their own PE from the executable module.

Which brings me to my question, how do I hook the entry point of a DLL? I want to implement that method because I need the DLL to be bound to the libraries it imports statically, so I can hook the LoadLibrary/GetProcAddress functions in before the DLL has a chance to load/import them in DLLMain. I'm assuming there is a way to do this by changing the entry point of the DLL, or by hooking a lower level function that handles calling a DLL entry point in kernel32.dll.

If the method I'm requesting has a better alternative, then I would gladly accept that solution as well if it achieves my desired effect.

My processor is an AMD Athlon II X2 250 that is x86-x64 compatible, and my operating system is Windows 7.

2 Answers 2

4

To answer the original question, what you can do is to hook LdrpCallInitRoutine in ntdll.dll. This function is used by DLL loading/unloading code to actually call the DLL entry point (DllMain) and also the TLS callbacks. The first argument is the address to be called:

BOOLEAN NTAPI LdrpCallInitRoutine(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
4
  • I'm changing this to the chosen answer, since this answers the question I asked in the OP. Aug 6, 2014 at 19:33
  • Question -- how do you find LdrpCallInitRoutine without debug symbols?
    – user541686
    Oct 25, 2016 at 18:26
  • @Mehrdad: you can that ask it in a new question; comments are for commenting/clarifications
    – Igor Skochinsky
    Oct 25, 2016 at 18:29
  • 1
    @IgorSkochinsky: it was for clarification. It's suggested in the answer but it's not even clear that it's possible in general.
    – user541686
    Oct 25, 2016 at 20:43
3

You should not be using IAT overwriting hooking method for the same reasons you mentioned. Use the inline hooking method with a JMP instruction to the target hook. You need to save the overwritten bytes somewhere as you need to use it as the trampoline. See this as an example of inline hook.

Using inline hook ensures that all (existing or future) modules loaded in the same address space will using the hooked functions no matter how they resolve the addresses of the APIs.

jbremer.org has good informative resources on API hooking.

3
  • I wouldn't say that an inline hook insures that all future modules will use the function, unless those modules use the same module that contains the hook. Aug 4, 2014 at 1:45
  • 1
    @CaptainObvious Of course. Suppose you inline hooked Kernel32.CreateFileA then calling some other function such as Gdi32.BitBlt would never trigger the hook. What I meant, that any module who calls CreateFileA would be using our hooked function.
    – 0xec
    Aug 4, 2014 at 1:56
  • @CaptainObvious In case you are not aware, every process has exactly a single copy of a dll in its address space. That means there is a single copy of the function CreateFileA no matter how many times you load kernel32 using LoadLibrary. In our case when we inline hook, it is hooked for once and for all.
    – 0xec
    Aug 4, 2014 at 2:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.