Launching window hook after madCHook injection

c++ / delphi package - dll injection and api hooking
SittingBull
Posts: 23
Joined: Fri Jun 03, 2005 2:17 pm

Launching window hook after madCHook injection

Post by SittingBull »

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
nildo
Posts: 249
Joined: Mon Mar 22, 2004 11:32 am
Contact:

Post by nildo »

You can hook GetMessage API.
SittingBull
Posts: 23
Joined: Fri Jun 03, 2005 2:17 pm

Post by SittingBull »

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.
nildo
Posts: 249
Joined: Mon Mar 22, 2004 11:32 am
Contact:

Post by nildo »

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.
Sure, it will cause overhead.

One alternative is to hook APIs like ShowWindow, CloseWindow, maybe
Send/Post Message, BringWindowToTop, SetForegroundWindow, and so on..
SittingBull
Posts: 23
Joined: Fri Jun 03, 2005 2:17 pm

Post by SittingBull »

:D 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...
dcsoft
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

Post by dcsoft »

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.
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: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.
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?

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
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

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...
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

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...
Should be OK. The DefWindowProc handling of the WM_CLOSE message will call DestroyWindow(), so hooking DestroyWindow() will work.

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.
No idea whether you can call SetWindowHookEx() from a service.

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.

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?
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: 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).
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: 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.
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.

This is a hard problem.

-- David[/url]
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

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.
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.
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

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.
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?

Thanks,
David
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

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.
SittingBull
Posts: 23
Joined: Fri Jun 03, 2005 2:17 pm

Post by SittingBull »

dcsoft wrote:Your new service should be able to call SetWindowsHookEx to inject your DLL when the new user logs in.
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: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?
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... :()

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.
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.
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.
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.
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.
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.
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?
dcsoft wrote:You can do CreateThread yourself. However, it's a bit troublesome...
:D 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.
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
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

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
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

dcsoft

Post by iconic »

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.
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

MSAA from Delphi

Post by dcsoft »

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.
I don't use Delphi, but it should be easy to port this C++ code:

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 );
You just call the Windows APIs RegisterWindowMessage() and SendMessageTimeOut(), then the Accessibility API ObjectFromLresult to get the IHTMLDocument2.

Regards,
David
Post Reply