hooking registry native api

just write whatever you want
Post Reply
chuck2000
Posts: 1
Joined: Mon Nov 22, 2004 4:46 pm

hooking registry native api

Post by chuck2000 »

Hi Madshi

First of all congratulations for your components and for your unique knowledge of windows programming. I' m building a registry monitor: I'm trying to build it without building a virtual device driver (like sysinternals "registry monitor"). I use the IAT Patching tecnique in order to intercept api calls and I built a dll that I inject in remote processes (the injection is realized using a system hook or directly injecting the dll through CreateRemoteThread). I tried to intercept call to the "registry api": the result is that I can intercept "win32 registry api" but not the "native registry api". Is there a theoretical motivation to this behaviour in the contest of api hooking ??

Thank you
Chuck2000
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: hooking registry native api

Post by madshi »

chuck2000 wrote:Is there a theoretical motivation to this behaviour in the contest of api hooking ??
What do you mean with that sentence? I don't really understand it.

Anyway, using IAT patching is okay, but you'll miss some API calls. Using CreateRemoteThread is also okay, but you must not use it on not-yet-initialized processes. If you mean SetWindowsHookEx when talking about "system hooks" then using that is okay, but you'll miss non-GUI processes.

You can work around all those problems by using madCodeHook instead... :D

You can of course also hook the native APIs, either by using IAT patching or by using madCodeHook.
JPMetal
Posts: 8
Joined: Tue Jun 14, 2005 6:25 pm

Post by JPMetal »

Which API call will be missed? Internals ones I guess.

Actually CreateRemoteThread initialize the process (I'm talking about NT since this function as far as I know isn't directly available in 9x).
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

JPMetal wrote:Which API call will be missed? Internals ones I guess.
That, too. But it's not the only thing. If a process is calling GetProcAddress before your hook is installed and stores the address in a variable and calls that later, you'll miss that calls, too. And what if the process calls GetProcAddress while your hook is already installed? You'd have to hook GetProcAddress, too, to make it work. But then you lose the ability to unhook again. Also: What happens if a process loads a new dll, after your hook was installed? You need to patch that dll, too.
JPMetal wrote:Actually CreateRemoteThread initialize the process
Not sure what you mean with that. You'll definately run into problems if you use remote threads on not-yet fully initialized processes. That's a fact.
JPMetal
Posts: 8
Joined: Tue Jun 14, 2005 6:25 pm

Post by JPMetal »

Well, usually EAT is patched so newly modules are patched by the loader and there's no need to patch GetProcAddress neither.

I mean that if you create a process with CREATE_SUSPEND and you call CreateRemoteThread with for example the ExitThread function address as starter it initializes the process.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

JPMetal wrote:Well, usually EAT is patched so newly modules are patched by the loader and there's no need to patch GetProcAddress neither.
Ok, using EAT patching plus IAT patching is a lot better. But that's not pure IAT patching, anymore. The sources found on the internet usually do only IAT patching (or am I wrong?). Anyway, when using IAT patching plus EAT patching you lose the ability to proper unhook. Also you'll still miss internal calls and you'll still also miss API calls of a process which called GetProcAddress before your hook was installed.
JPMetal wrote:I mean that if you create a process with CREATE_SUSPEND and you call CreateRemoteThread with for example the ExitThread function address as starter it initializes the process.
Yes, it does. But that's exactly the problem! If that remote thread does the initialization, all dlls will remember this remote thread as being the "main thread". In the moment the remote thread closes, the dlls will lose their "main thread". Some dlls/processes may get along with that. But there are some dlls/processes, which react strangely afterwards.
JPMetal
Posts: 8
Joined: Tue Jun 14, 2005 6:25 pm

Post by JPMetal »

madshi wrote:Ok, using EAT patching plus IAT patching is a lot better. But that's not pure IAT patching, anymore. The sources found on the internet usually do only IAT patching (or am I wrong?). Anyway, when using IAT patching plus EAT patching you lose the ability to proper unhook. Also you'll still miss internal calls and you'll still also miss API calls of a process which called GetProcAddress before your hook was installed.
Yes, you are right, it isn't just IAT patching then.
Why do you think that you lose the ability to proper unhook? I would first unpatch every IAT and EAT (restoring the original) and then unload the injection/patching DLL (not the 'detours' one off course but that has more to do with GetProcAddress).

You are right about internal functions and previous GetProcAddress they are both lost. The second could be circunvented writing a service.
madshi wrote:Yes, it does. But that's exactly the problem! If that remote thread does the initialization, all dlls will remember this remote thread as being the "main thread". In the moment the remote thread closes, the dlls will lose their "main thread". Some dlls/processes may get along with that. But there are some dlls/processes, which react strangely afterwards.
As far as I know all NT versions except Win2K work perfectly maybe I'm wrong.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

JPMetal wrote:Why do you think that you lose the ability to proper unhook? I would first unpatch every IAT and EAT (restoring the original) and then unload the injection/patching DLL
(1) IAT + EAT is patched.
(2) Calc.exe calls "blaApi := GetProcAddress(bla)".
(3) Because of EAT patching "blaApi" now points to your hook callback function.
(4) You unpatch IAT + EAT, but this doesn't change the "blaApi" variable.
(5) You unload your DLL.
(6) Calc.exe calls "blaApi".
(7) Crash, because "blaApi" still points to your hook callback function.
JPMetal wrote:As far as I know all NT versions except Win2K work perfectly maybe I'm wrong.
It doesn't have much to do with the OS:

(1) You start Calc.exe with CREATE_SUSPENDED.
(2) You call CreateRemoteThread on Calc.
(3) All dlls are called with DLL_PROCESS_ATTACH in the context of your remote thread.
(4) Delphi dlls now do "MainThreadID := GetCurrentThreadID".
(5) Your remote thread ends.
(6) Delphi dlls try to contact the main thread e.g. by doing PostThreadMessage(MainThreadID, ...).
(7) This doesn't work, cause the thread has already terminated. Or maybe there's even a new thread (of another process) which now reuses the ID that your remote thread had.

Of course it depends on how the exes and dlls are written. But there is the potential problem that they remember your remote thread as being the main thread ID and thus behave incorrectly. This is no theoretical problem. It actually exists very much. You can find lots of discussion about this problem if you search with the right key words in google.
JPMetal
Posts: 8
Joined: Tue Jun 14, 2005 6:25 pm

Post by JPMetal »

madshi wrote:(1) IAT + EAT is patched.
(2) Calc.exe calls "blaApi := GetProcAddress(bla)".
(3) Because of EAT patching "blaApi" now points to your hook callback function.
(4) You unpatch IAT + EAT, but this doesn't change the "blaApi" variable.
(5) You unload your DLL.
(6) Calc.exe calls "blaApi".
(7) Crash, because "blaApi" still points to your hook callback function..
In the 5 point I unload the inject/patcher DLL but not the detour DLL.

You are right about CreateRemoteThread, I wasn't thinking about the entry routines of dlls loaded by the Windows loader. It can be circunvented running the thread until the main one ends.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

JPMetal wrote:In the 5 point I unload the inject/patcher DLL but not the detour DLL.
But still your hook callback function is called instead of the original API. That's what I meant with that you cannot properly unhook. You can also not unload your detour DLL without risking crashes.
JPMetal wrote:It can be circunvented running the thread until the main one ends.
Not really. Let's say the exe calls PostThreadMessage(MainThreadID, ...) and relies on that this message gets properly received and handled. Your remote thread could receive this message by using a message loop, but your remote thread doesn't know what to do with the message, because DispatchMessage doesn't work for PostThreadMessage messages.

Or another situation: Let's say a dll is calling CreateWindow during DLL_PROCESS_ATTACH. Suddenly the window belongs to your thread and not to the "real" main thread. This can make problems, even if you add a proper message loop to your remote thread. Because the real main thread will do some part of the work, and your remote thread will do some other parts of the work. That are 2 threads working with global resources which the original programmer thought would all be handled by one thread only. The program can e.g. run into thread related issues. E.g. your remote thread might (as a result of a DispatchMessage call) remove items from a list, while the real main thread at the same time loops through the list. Without synchronization this can result in crashes.
JPMetal
Posts: 8
Joined: Tue Jun 14, 2005 6:25 pm

Post by JPMetal »

madshi wrote:But still your hook callback function is called instead of the original API. That's what I meant with that you cannot properly unhook. You can also not unload your detour DLL without risking crashes.
Actually just the Detour DLL would be called and that's why the inject/patching DLL can be unloaded and the detour one can't.
madshi wrote:Not really. Let's say the exe calls PostThreadMessage(MainThreadID, ...) and relies on that this message gets properly received and handled. Your remote thread could receive this message by using a message loop, but your remote thread doesn't know what to do with the message, because DispatchMessage doesn't work for PostThreadMessage messages.

Or another situation: Let's say a dll is calling CreateWindow during DLL_PROCESS_ATTACH. Suddenly the window belongs to your thread and not to the "real" main thread. This can make problems, even if you add a proper message loop to your remote thread. Because the real main thread will do some part of the work, and your remote thread will do some other parts of the work. That are 2 threads working with global resources which the original programmer thought would all be handled by one thread only. The program can e.g. run into thread related issues. E.g. your remote thread might (as a result of a DispatchMessage call) remove items from a list, while the real main thread at the same time loops through the list. Without synchronization this can result in crashes.
Fair enough, you are right.
Post Reply