hooking registry native api
hooking registry native api
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
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
Re: hooking registry native api
What do you mean with that sentence? I don't really understand it.chuck2000 wrote:Is there a theoretical motivation to this behaviour in the contest of api hooking ??
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...
You can of course also hook the native APIs, either by using IAT patching or by using madCodeHook.
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:Which API call will be missed? Internals ones I guess.
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 wrote:Actually CreateRemoteThread initialize the process
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.
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.
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:Well, usually EAT is patched so newly modules are patched by the loader and there's no need to patch GetProcAddress neither.
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 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, you are right, it isn't just IAT patching then.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.
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.
As far as I know all NT versions except Win2K work perfectly maybe I'm wrong.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.
(1) IAT + EAT is patched.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
(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.
It doesn't have much to do with the OS:JPMetal wrote:As far as I know all NT versions except Win2K work perfectly maybe I'm wrong.
(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.
In the 5 point I unload the inject/patcher DLL but not the detour DLL.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..
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.
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:In the 5 point I unload the inject/patcher DLL but not the detour DLL.
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.JPMetal wrote:It can be circunvented running the thread until the main one ends.
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.
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: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.
Fair enough, you are right.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.