Launching window hook after madCHook injection
-
- Posts: 23
- Joined: Fri Jun 03, 2005 2:17 pm
Launching window hook after madCHook injection
hi all,
I previously had an injection mechanism that used the windows SetWindowsHook function in order to inject my dll into all running processes. This was ok for me because i indeed needed to intercept th WH_CBT hook or the WH_SHELL so i could control window switching on the system.
Yet when changing to a new account the hook wasn't installed, so i needed to move to the madchook dll injection system, providing a system service that launches on start-up and injects the dll system wide.
Now the dll injects perfectly in all system process's which ever account they belong to, the problem I’m now facing is the need to hook the messaging mechanism has with SetWindowsHook so that i can intercept the WH_CBT messages in order to control window usage.
I've tried unsuccessfully to launch the SetWindowsHook from within the injected dll.
Can anyone figure this out? Any help is "very welcome".
Thanks in advanced,
Sitting Bull
I previously had an injection mechanism that used the windows SetWindowsHook function in order to inject my dll into all running processes. This was ok for me because i indeed needed to intercept th WH_CBT hook or the WH_SHELL so i could control window switching on the system.
Yet when changing to a new account the hook wasn't installed, so i needed to move to the madchook dll injection system, providing a system service that launches on start-up and injects the dll system wide.
Now the dll injects perfectly in all system process's which ever account they belong to, the problem I’m now facing is the need to hook the messaging mechanism has with SetWindowsHook so that i can intercept the WH_CBT messages in order to control window usage.
I've tried unsuccessfully to launch the SetWindowsHook from within the injected dll.
Can anyone figure this out? Any help is "very welcome".
Thanks in advanced,
Sitting Bull
-
- Posts: 23
- Joined: Fri Jun 03, 2005 2:17 pm
Sure, it will cause overhead.SittingBull wrote:hi, nildo,
And thanks for the fast reply, i'll look into this.
Wouldn't that cause an excesive overhead on the system? - having to intercept every GetMessage only to choose from a couple of them. I only need to know when a window gets created, activates or get's destroyed.
One alternative is to hook APIs like ShowWindow, CloseWindow, maybe
Send/Post Message, BringWindowToTop, SetForegroundWindow, and so on..
-
- Posts: 23
- Joined: Fri Jun 03, 2005 2:17 pm
thanks once again,
Yes i belive that hooking the windows functions could be am optimum solution and indeed I'm considering what you said. It's far more efficient to intercept those function calls, then hooking GetMessage.
Though I would like to now if it would be possible to somehow launch the windows hook on WH_CBT.
Excuse my persistence, it's just that it would really be easier for me to adapt my existing code to this hook than to intercept all the API used for this purpose...
Yes i belive that hooking the windows functions could be am optimum solution and indeed I'm considering what you said. It's far more efficient to intercept those function calls, then hooking GetMessage.
Though I would like to now if it would be possible to somehow launch the windows hook on WH_CBT.
Excuse my persistence, it's just that it would really be easier for me to adapt my existing code to this hook than to intercept all the API used for this purpose...
-
- Posts: 380
- Joined: Sat Dec 11, 2004 2:11 am
- Location: San Francisco Bay Area, CA USA
- Contact:
Re: Launching window hook after madCHook injection
Your new service should be able to call SetWindowsHookEx to inject your DLL when the new user logs in. I don't see why you need Madshi's dll injection routines in your new scheme, if SetWindowsHookEx was doing fine for you. (I also used SetWindowsHookEx to inject my dll, and that had some incompatibilties with AOL; Madshi's didn't. So there may be other reasons to use Madshi's excellent stuff.)SittingBull wrote: I previously had an injection mechanism that used the windows SetWindowsHook function in order to inject my dll into all running processes. This was ok for me because i indeed needed to intercept th WH_CBT hook or the WH_SHELL so i could control window switching on the system.
Yet when changing to a new account the hook wasn't installed, so i needed to move to the madchook dll injection system, providing a system service that launches on start-up and injects the dll system wide.
Here, I don't understand. Why does your DLL need to call SetWindowsHookEx() once it's injected? The DLL doesn't need to be injected before calling SetWindowsHookEx. Your service would call SetWindowsHookEx to both install the CBT hook AND inject your DLL to handle it, right?SittingBull wrote:Now the dll injects perfectly in all system process's which ever account they belong to, the problem I’m now facing is the need to hook the messaging mechanism has with SetWindowsHook so that i can intercept the WH_CBT messages in order to control window usage. I've tried unsuccessfully to launch the SetWindowsHook from within the injected dll.
Are you calling SetWindowsHookEx twice, once to inject your DLL, and another to set the WH_CBT hook? Why?
Also, if this is for Win98 or later, you can use MS Accessibility --- SetWinEventHook() to get the same info in a much cleaner fashion.
Regards,
David
http://www.dcsoft.com
Generally there are multiple ways to solve the problem. Honestly I've not done much message hooking yet, so I don't know which is the optimal solution in your case.
Nildo suggested hooking some APIs instead of using SetWindowsHookEx. That is one of the possible solutions and it might work out just fine. One problem I see is how to find out when a window got destroyed. I mean is hooking DestroyWindow good enough? What if you use PostMessage(window, WM_CLOSE, 0, 0)? Will that always end up in DestroyWindow? I'm not sure, maybe it will...
I've no idea how SetWindowsHookEx behaves when being called from a service. I've also no idea how it behaves when being called from a dll. Basically I agree with David: Why stopping to use SetWindowsHookEx, if it worked fine for you? Okay, you had some problems with different accounts. But maybe you can solve that without having to use madCodeHook's injection? As David also said, madCodeHook's dll injection might have other advantages, so maybe it's good to not use SetWindowsHookEx for dll injection, anymore. Not really sure about this.
A third possibility would be to use madCodeHook for DLL injection and SetWindowsHookEx for message hooking only (this was also hinted at by David). This would work by calling SetWindowsHookEx with slightly different parameters. Your hook dll could call it so that it only effects the current process. That should work fine. As a result each copy of your hook dll which is loaded in each running process would call SetWindowsHookEx for its own process. Now I'm not sure how good SetWindowsHookEx gets along with being activated once for each process. Might be bad for performance. Might even be very good for performance. I simply don't know.
I guess you'll have to experiment with all the different solution possibilities. It might be that you'll even find that one solution is optimal for the NT family, and another one for the win9x family. SetWinEventHook sounds interesting, I didn't know that before...
Nildo suggested hooking some APIs instead of using SetWindowsHookEx. That is one of the possible solutions and it might work out just fine. One problem I see is how to find out when a window got destroyed. I mean is hooking DestroyWindow good enough? What if you use PostMessage(window, WM_CLOSE, 0, 0)? Will that always end up in DestroyWindow? I'm not sure, maybe it will...
I've no idea how SetWindowsHookEx behaves when being called from a service. I've also no idea how it behaves when being called from a dll. Basically I agree with David: Why stopping to use SetWindowsHookEx, if it worked fine for you? Okay, you had some problems with different accounts. But maybe you can solve that without having to use madCodeHook's injection? As David also said, madCodeHook's dll injection might have other advantages, so maybe it's good to not use SetWindowsHookEx for dll injection, anymore. Not really sure about this.
A third possibility would be to use madCodeHook for DLL injection and SetWindowsHookEx for message hooking only (this was also hinted at by David). This would work by calling SetWindowsHookEx with slightly different parameters. Your hook dll could call it so that it only effects the current process. That should work fine. As a result each copy of your hook dll which is loaded in each running process would call SetWindowsHookEx for its own process. Now I'm not sure how good SetWindowsHookEx gets along with being activated once for each process. Might be bad for performance. Might even be very good for performance. I simply don't know.
I guess you'll have to experiment with all the different solution possibilities. It might be that you'll even find that one solution is optimal for the NT family, and another one for the win9x family. SetWinEventHook sounds interesting, I didn't know that before...
-
- Posts: 380
- Joined: Sat Dec 11, 2004 2:11 am
- Location: San Francisco Bay Area, CA USA
- Contact:
Should be OK. The DefWindowProc handling of the WM_CLOSE message will call DestroyWindow(), so hooking DestroyWindow() will work.madshi wrote:I mean is hooking DestroyWindow good enough? What if you use PostMessage(window, WM_CLOSE, 0, 0)? Will that always end up in DestroyWindow? I'm not sure, maybe it will...
No idea whether you can call SetWindowHookEx() from a service.madshi wrote:I've no idea how SetWindowsHookEx behaves when being called from a service. I've also no idea how it behaves when being called from a dll.
http://groups-beta.google.com/group/mic ... a0b29118b6
indicates it's not possible. I tried it from the DllMain(), and it didn't work, but that was because of the hook type requiring to be systemwide (WH_KEYBOARD_LL); a WH_CBT hook might work.
In general, one limitation of madCodeHook is that the only time your code can run after injection is from DllMain(), when, all threads are stopped, and I've no idea what GetCurrentThreadId() will return when called in DllMain()! For this reason, things like setting hooks might not work. Whereas if you inject the dll with SetWindowsHookEx(WH_GETMESSAGE, ...), your code can get control when processing the first message after that.
The way I've resolved this in the past is to arrange for my .exe to start running when other users log in. So there is one instance of my .exe per user, which isn't ideal, but it gets around the problem quickly.madshi wrote: Basically I agree with David: Why stopping to use SetWindowsHookEx, if it worked fine for you? Okay, you had some problems with different accounts. But maybe you can solve that without having to use madCodeHook's injection?
But SetWindowsHookEx() takes care of injecting the dll into the target process! No need to use any other DLL injection. That's why I'm confused.madshi wrote: As David also said, madCodeHook's dll injection might have other advantages, so maybe it's good to not use SetWindowsHookEx for dll injection, anymore. Not really sure about this.
A third possibility would be to use madCodeHook for DLL injection and SetWindowsHookEx for message hooking only (this was also hinted at by David).
It's unclear whether the original solution was a systemwide hook that was installed for every process, or just for specific target processes. I think it was a systemwide hook, because he was complaining that it worked fine except when another user logged in, as if he was expecting Windows to inject the hook into the other user's processes automatically.madshi wrote: This would work by calling SetWindowsHookEx with slightly different parameters. Your hook dll could call it so that it only effects the current process. That should work fine. As a result each copy of your hook dll which is loaded in each running process would call SetWindowsHookEx for its own process.
This is a hard problem.
-- David[/url]
There are 2 totally different situations:dcsoft wrote:In general, one limitation of madCodeHook is that the only time your code can run after injection is from DllMain(), when, all threads are stopped, and I've no idea what GetCurrentThreadId() will return when called in DllMain()! For this reason, things like setting hooks might not work.
(1) When the hook dll is injected into an already running process, the dll is loaded by a temporare secondary thread. This secondary thread will terminate as soon as DllMain is through. If you do SetWindowsHookEx in this thread, Windows might be tempted to uninstall the SetWindowsHookEx again directly after DllMain (after the thread shuts down).
(2) When the hook dll is injected into a newly created process, the dll is loaded by the main thread. In this case using SetWindowsHookEx should work fine.
-
- Posts: 380
- Joined: Sat Dec 11, 2004 2:11 am
- Location: San Francisco Bay Area, CA USA
- Contact:
Ah, thanks for the info. All my usage of madCodeHook to date has been #1. If the code is run on a temporary thread, then my code can't even create any windows (since the window is associated with the current thread). It's probably not possible, but could you build some sort of callback mechanism into madCodeHook so I can specify a function madCodeHook calls when I can do things like create windows and set hooks on a known good thread? Or can I do a CreateThread() from DllMain and do all my stuff on that thread?madshi wrote: There are 2 totally different situations:
(1) When the hook dll is injected into an already running process, the dll is loaded by a temporare secondary thread. This secondary thread will terminate as soon as DllMain is through. If you do SetWindowsHookEx in this thread, Windows might be tempted to uninstall the SetWindowsHookEx again directly after DllMain (after the thread shuts down).
(2) When the hook dll is injected into a newly created process, the dll is loaded by the main thread. In this case using SetWindowsHookEx should work fine.
Thanks,
David
You can do CreateThread yourself. However, it's a bit troublesome. You need to make sure that your thread gets properly closed (and the windows properly destroyed) before your dll is unloaded. Furthermore some processes might react allergically to just another thread. That should be rare, but can happen, especially in win9x. madCodeHook uses a special technique in win9x which hides the dll injection thread from the apps to make sure that no stability problems occur.
The main problem with closing your private thread is that during DLL_PROCESS_DETACH your private thread doesn't get time slices, anymore. So the only way to close it is to use TerminateThread, which is very bad and can lead to follow up problems like deadlocks or resources/memory leaks. So if you create threads in your hook dll, then for stabilities sake you should make sure that those threads are closed before you unload/uninject the dll.
The main problem with closing your private thread is that during DLL_PROCESS_DETACH your private thread doesn't get time slices, anymore. So the only way to close it is to use TerminateThread, which is very bad and can lead to follow up problems like deadlocks or resources/memory leaks. So if you create threads in your hook dll, then for stabilities sake you should make sure that those threads are closed before you unload/uninject the dll.
-
- Posts: 23
- Joined: Fri Jun 03, 2005 2:17 pm
This is one thing I couldn't yet figure! How can one check wether a login has been done on windows? Is there some kind of notification on the system, or can it be done trough API hooking?dcsoft wrote:Your new service should be able to call SetWindowsHookEx to inject your DLL when the new user logs in.
We'll this was just a tought. I belived that once my dll got injected, i could still use windows hooks to simulate the effect i had before. So first I would inject the dll using madCHook's lib then inside the target process use setwindowshookex to monitor WH_CBT messages. (I did tryed it, unsuccessfully... )dcsoft wrote:Here, I don't understand. Why does your DLL need to call SetWindowsHookEx() once it's injected?...
Are you calling SetWindowsHookEx twice, once to inject your DLL, and another to set the WH_CBT hook? Why?
Well SetWindowsHookEx worked (work's...) fine when I launch the hook when a user get's logged in, the problem is that i need for my program to continue working in other accounts. Imagine a user switch's account using winXP fast user switching, the only way I can monitor his account is by creating a new main process and launching the hook's again, in most cases this wouldn't be of much of a concern wouldn't it be for the fact that the main process takes up a large amount of memory (It's a parental control software), because it needs to load a bunch of data structures, in order to filter site's being visited, and controling a series of other things.madshi wrote:I've no idea how SetWindowsHookEx behaves when being called from a service. .... Why stopping to use SetWindowsHookEx, if it worked fine for you? Okay, you had some problems with different accounts. But maybe you can solve that without having to use madCodeHook's injection? As David also said, madCodeHook's dll injection might have other advantages, so maybe it's good to not use SetWindowsHookEx for dll injection, anymore. Not really sure about this.
So this is why I have the need of launching only one main process, in system account, and using madCHook for system wide hooking, since SetWindowsHookEx didn't work, yet I need to trap wich application is being used, so the need for the WH_CBT to track down HCBT_ACTIVATE, HCBT_CREATEWND, HCBT_DESTROYWND, HCBT_MINMAX.
This problem came up when considering the winXP fast user switching, has with the logout/login there were no problems. (Software's like netNanny simply turn off winXP fast user switching, though i belive there is no need in doing so...) and would like to workarround this problem.dcsoft wrote:It's unclear whether the original solution was a systemwide hook that was installed for every process, or just for specific target processes. I think it was a systemwide hook, because he was complaining that it worked fine except when another user logged in, as if he was expecting Windows to inject the hook into the other user's processes automatically.
So, imagining I launch the my main program as a service, while windows is starting up, every spawned process when a user logs in get's injected in their main thread?madshi wrote:(2) When the hook dll is injected into a newly created process, the dll is loaded by the main thread. In this case using SetWindowsHookEx should work fine.
I found this out the hardway... In early stage of development I did used an active mode of comunication between my main process and my injected dll's, meaning that the main program could direcly comunicate with the injected dll, so there was the need to spawn a listening thread in the injected dll. This led the system unstable, crashing some process's when the dll got ejected. The way i solved it was spaning another thread that would listen for an eject dll event, so when I was to eject my dll I just signaled that event so that all injected dll's got ready for uninjecting. After a small wait (100 miliseconds, I think) the main process would then uninject the dll.dcsoft wrote:You can do CreateThread yourself. However, it's a bit troublesome...
Though this was not garanteed to work all the times, I did used the rather crude tactic of terminating the thread if it wouldn't terminate by the global shutdown event, by calling TeminateThread on DLL_PROCESS_DETACH.
As for the main issue I'm considering this options:
.: Intercepting the GetMessage / PeekMessage, and listening for WM_CLOSE, WM_ACTIVATEAPP and all other messages that lead to the window manipulation behaviours (still trying to figure them all out, Spy++ has been a gracefull ally).
.: Intercepting all Window's related API (can be quite anoying, though more efficient)
.: Try and use SetWindowHookEx on the current process, enumerating all threads and calling it once for each thread.
Thank you all for your repplies, this thread has been very elucidative, not only in the injection theme but in many other aspects of programming.
Again... many, many thanks,
Sitting Bull
-
- Posts: 380
- Joined: Sat Dec 11, 2004 2:11 am
- Location: San Francisco Bay Area, CA USA
- Contact:
SittingBull,
You can register for logon/logoff notifications with WTSRegisterSessionNotification(). I'm not sure this will help you though.
The basic problem you have is that you need to get your dll injected when a new user logs in. It sounds like you need to create a small .exe that runs automatically (because it is in the registry Run key or Startup folder)when the user logs in which does the SetWindowsHookEx(). This does the work of injecting your dll, you don't need madshi's library to do so. It seems backwards to use an injection library in order to call SetWindowsHookEx() WHOSE PURPOSE IS TO INJECT YOUR DLL AFTER ALL.
I really would recommend you avoid the WH_CBT hook and instead use MS Active Accessibility - SetWinEventHook().
At any rate, the small .exe would run in each user session and get notified of window creation, destruction, etc. events (either using the WH_CBT hook, or the MS Active Accessibility). It would then forward these messages to your big .exe (the one with all the data structures) using madshi's ipc queue. This will work even if the big .exe is in another user session as madshi's ipc queue works across sessions.
Would this work?
-- David
You can register for logon/logoff notifications with WTSRegisterSessionNotification(). I'm not sure this will help you though.
The basic problem you have is that you need to get your dll injected when a new user logs in. It sounds like you need to create a small .exe that runs automatically (because it is in the registry Run key or Startup folder)when the user logs in which does the SetWindowsHookEx(). This does the work of injecting your dll, you don't need madshi's library to do so. It seems backwards to use an injection library in order to call SetWindowsHookEx() WHOSE PURPOSE IS TO INJECT YOUR DLL AFTER ALL.
I really would recommend you avoid the WH_CBT hook and instead use MS Active Accessibility - SetWinEventHook().
At any rate, the small .exe would run in each user session and get notified of window creation, destruction, etc. events (either using the WH_CBT hook, or the MS Active Accessibility). It would then forward these messages to your big .exe (the one with all the data structures) using madshi's ipc queue. This will work even if the big .exe is in another user session as madshi's ipc queue works across sessions.
Would this work?
-- David
dcsoft
have you any good msaa delphi articles? i wanted to learn oleacc com and msaa apis but delphi seems to lack any good documentation, its all in c/c++. I'm wanting to adjust msn messengers window with msaa but it's class is internet explorer server and it seems hard to do, getting fully marshalled pointer to the ihtmldocument2 interface is what i read about but have had no luck doing.
-
- Posts: 380
- Joined: Sat Dec 11, 2004 2:11 am
- Location: San Francisco Bay Area, CA USA
- Contact:
MSAA from Delphi
I don't use Delphi, but it should be easy to port this C++ code:iconic wrote:have you any good msaa delphi articles? i wanted to learn oleacc com and msaa apis but delphi seems to lack any good documentation, its all in c/c++. I'm wanting to adjust msn messengers window with msaa but it's class is internet explorer server and it seems hard to do, getting fully marshalled pointer to the ihtmldocument2 interface is what i read about but have had no luck doing.
Code: Select all
// New Internet Explorer_Server" window not yet being tracked;
// get IHTMLDocument2 object:
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hwnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
CComPtr<IHTMLDocument2> spDoc;
HRESULT hr = ObjectFromLresult( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
Regards,
David