I want to intercept messages that are being sent to a window in a different process. What is the best way to do this? I can't see the messages when I use the WH_GETMESSAGE hook, and I'm not sure if I can subclass across processes? Any help would be much appreciated.
You need to inject your own code into the process that owns the windows you wish to intercept messages from. Fortunately, SetWindowsHookEx() makes this fairly easy, although you may have a bit of trouble at first if you've only used it for in-process hooking up to now.
I can recommend two excellent articles on the subject:
Joseph Newcomber's Hooks and DLLs
Robert Kuster's Three Ways to Inject Your Code into Another Process
If the message is sent rather than posted WH_GETMESSAGE won't see it. You need WH_CALLWNDPROC. If you're working across processes you'll need a system-wide hook in a DLL. You don't mention how you invoked SetWindowsHookEx, so I don't know if your hooking failed because it wasn't global, or because the message you were looking for was sent.
If you haven't worked with system-wide hooks before, I have an example of a system-wide hook on my website here. That's a keyboard hook, but the principle is the same.
Stop me if I'm unintentionally talking down here - your question was so short I can't infer your expertise level. But messing around with hooks does imply some experience...
Related
So I have spent that past week and a half working on code to simply setup the hook procedure for wh_shell for a program that will replace explorer.exe in the registry and will run as the main desktop program. There seems to be very little information and sources for using this outside of just the windows API which is a bit undescriptive and doesn't explain everything to a great detail. For some reason I just cant get it to work, no matter if I run it inside of explorer.exe, or if I replace the register and make it the default shell. I'm going to ask a couple of things in this post because I think that if you can answer one of these questions you likely have the answer to more.
So first I just have a question about hooks in general: When I run the SetWindowsHookEx(...) function -resource below- it says for var lpfn that a dll is not necessary if the hook is only used to monitor the current process. Now obviously when monitoring events such as window_created, those are events within a different processes which makes me think that the hookproc has to be within a DLL(which is how ive programmed so far). But this is questionable to me because when u are running SetWindowsHookEx(...) the process I wish to monitor do not yet exist until the user decides to start them. Do these processes notify the system when wh_shell events are being done so that I my hook doesnt need to get placed into every process upon creation, or is it more like when I run SetWindowsHookEx(...) with wh_shell that it will place a hook in all processes when the are created. The second resource states that the system just calls the hookproc when these things happen, so then do I even need a DLL, or what process does it need to be hooked to because I dont think it needs to be hooked into everything.
So second I have a question regarding setting my process as default shell - see resources - the resource states any process that registers itself as the default shell(which I assume is just modifying the registry to my process, if not and there is more please let me know) needs to call the SystemsParameterInfo(...) function. So first, does this func need to be called before running SetWindowsHookEx(...) or is there some expected spot it should be elsewhere in my code? Then in regards to the other variables it doesnt specify for, just curious what the recommended would be to set them as, like what are they set as for explorer.exe, and maybe a few other examples(including things NOT to do).
Finally for the sake of testing, using the console will be the most helpful to me here. The console will be used for input to run functions and commands for now(like open the register and swap back the shell to explorer.exe). If my hookproc is within a DLL, I need it to output some messages, I dont want to muddle the same console and I also dont even know if it will output to the same console, so what might be a recommended or potential solution for outputs(again this is temporary and for testing so it doesnt have to be perfect or even great)?
Also I would think windows 11 shouldn't be an issue, but I havent tested on windows 10 system...
I havent included any code as Im pretty sure most of this stuff can be answered without it and that its so few lines of code that its not like typical questions where its like examine my code and help me, maybe some example code you can show me would be really helpful.
Thankyou!
SetWindowsHookEx(...)
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa
defaultShell
https://learn.microsoft.com/en-us/windows/win32/winmsg/about-hooks#wh_shell
regards to WH_SHELL section
Testing Environment:
Windows 11 vm running in Hyper-V Manager
You haven't mentioned an important parameter in your description and that is the last argument of SetWindowsHookEx, the thread id.
When it is set to 0 then ..
'[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.'
That said, then like everything in Windows programming nothing is as what the documentation states, its as if the documentation is a wish-list Microsoft will like Windows to be when it grows up.
Actually even if you manage to get everything right you will see that the shell messages you will get will be VERY few compared to what the documentation states.
I am working on the same issue and when I get it going I will post the results here.
I was sitting around bored and thought of this idea. Is it possible to change the WM_DESTROY code so that it will do something else instead of closing the application. But, I don't think this will work, but does that keep it from closing when you try to close the application from the task manager in windows. Also, is there a way to remove my application from the task manager so they wouldn't be able to do that in the first place? So, is this possible or do you have a better way? I have googled this and have tried this, but I want to ask the experienced here to answer this question.
BTW, I am not making a virus.
Windows Task Manager will use TerminateProcess to "close" a process - which is a good thing if your program has accidentally or on purpose got a broken VM_DESTROY handler.
There are supposedly ways to mess about with the process list that hides a process. But I don't actually know how that is done othat than very fundamentally (the process list is a linked list, and you can "unlink" a process from the list, and it "disappears"). Obviously doing so would be the type of thing that virus, trojan's, spyware, etc does, and I don't see any reason why you would want to do that in a legitimate application.
Edit: And hiding the application just means it doesn't appear in the list of processes in task manager. If you KNOW that the task exists (and you could for example "guess" based on system activity or some such), it can still be killed using it's process ID by some application that has enough privileges to terminate the process.
you shoud read win32 api demo. when mainwindow receives WM_DESTROY message, call postquitmessage([exitcode]) to end message loop。
I have some question about WH_MOUSE. From what I've read, by putting the hook into a DLL it injects processes. Does it mean that capturing the mouse will work on my desktop, menu start etc. too? And what about title bar of applications? I've seen some posts over the Internet with such problems, but don't know if they failed with something or there's some kind of limitation (or another approach).
I also have a question about performance between WH_MOUSE and WH_MOUSE_LL. I found somewhere that the WM_MOUSE is faster than WH_MOUSE_LL, but is it really noticeable? If so in what situations it can slow system that much that we can notice that? If I want to record only clicks of the mouse and keyboard would WH_MOUSE_LL be efficient?
Thanks!
Both hooks get you mouse input anywhere on the screen (other than cases listed below), they are essentially the same from this high-level functional point of view.
Both are subject to UIPI: neither hook will get you mouse input when the mouse is over an elevated process.
Low-level hooks don't require a DLL, so can be used by C#. The other type requires a separate DLL written in unmanaged code (C/C++).
If running on a 64-bit machine, where you can have a mix of 32-bit and 64-bit processes running, a low-level hook will receive events from both types of processes, but the other type of hook will only see events from processes of the same 'bitness' as itself (this limitation derives from the use of a hook DLL; a 32-bit hook DLL can only hook into 32-bit processes, and similarly for 64-bit.) So if you care about this case, with a LL hook you need just one process, whereas with the other type of hook, you need two cooperating processes, one for 32 and one for 64.
LL hook requires a message loop to be running.
LL hooks are simpler to write, since the callback happens in your own process, so you can access your own global variables and so on. With the other type of hook, the callback happens in another process, so you have to do extra work to communicate the information back to your main process. (In both cases, you should keep the code in your callback minimal; just do basic filtering and checking, do any significant work from your mainline code, not the callback.)
LL hooks are 'slower' because the input notification is marshaled to your process, processed there, and then the context switches back to the original process again. With the other type of hook, there's no context switch. This may or may not be noticeable to a user, however, and may depend on what you are doing in the callback, how your are handing the information, how long the hook is installed for, and other factors.
The issue with the title bar seems to be addressed in this question; summary is that you get WM_NCMOUSEMOVE messages over the titlebar (and other non-client areas), WM_MOUSEMOVE elsewhere, so you have to check for both.
My 2c: if you are writing a simple utility or coding for fun, go with _LL; it's considerably easier and handles most of the trickier cases for you; you don't have to worry about 64/32bit issues or communicating between processes, so you get up and running sooner. When you've got your app logic working, you can convert the code to the other type of hook later if needed. On the other hand, if you want a more 'professional' app that is a 'good citizen' and minimizes its impact on other apps, then the other type of hook may be more appropriate; but as with all things perf releated, measure first, don't assume, so even then perhaps best to start of with a _LL hook anyway.
I am doing a VoIP program where I use keyboard hook to check push-to-talk button is pressed down.
It works locally from the process which installs the hook, but my aim is to have it check all global input too.
Here's what I use:
SetWindowsHookEx(WH_KEYBOARD,hook_hookproc,hookInst,0);
According to MSDN and other sources, I need to inject my hooking dll into all other processes... which would be painful, and I doubt ventrilo/teamspeak etc does that. Is it possible to inject it unto the system process, and then all child processes (everything) inherit the hook call that way? Or do you HAVE to inject it into every single process?
cheers
A global hook like WH_KEYBOARD indeed requires a DLL that can be injected. You typically have to add some IPC code to tell somebody else about it. Beware that you are crossing a process boundary doing this so you need something like a pipe to talk.
Have you considered using a low-level keyboard hook (WH_KEYBOARD_LL). It doesn't require an injectable DLL, Windows switches context to your process to call the hook. It is almost always good enough to detect a specific keystroke, perhaps combined with GetAsyncKeyState() to check for modifier keys.
A hotkey registered with RegisterHotKey() could perhaps work as well. It should be your first choice since it has much less impact on the machine.
I'd like to execute some code whenever a (any!) message box (as spawned by the MessageBox Function) is shown in another process. I didn't start the process I'm monitoring.
I can think of three approaches:
Install a global CBT Hook procedure which tells me whenever a window is created on the desktop. Then, check whether the window belongs to the process I'm monitoring and whether the class name is #32770 (which is the class name of dialogs according to the About Window Classes page at the MSDN). This would probably work, but it would pull the DLL which contains the hook procedure into virtually every process on the desktop, and the hook procedure gets called a lot. It smells like a potential perfomance problem.
Try to subclass the #32770 system window class (is this possible at all?) and look for WM_CREATE messages in my custom window procedure.
Intercept the MessageBox Function API call (even though the remote process is running already!) and call my code from the hook function.
So far, I only know that the first idea is feasible, but it seems really inefficient. Can anybody think of a simpler solution than that to this problem?
I can't think of any efficient solution that doesn't involve injecting code into the other process (this is basically what many types of hooks do by the way). But if you are willing to go down that path, you can intercept calls to MessageBox.
Spend some time stepping through into a call to MessageBox in the debugger in assembly language mode and you'll see that it's an indirect call through a lookup table (that's how exports work). so if you can get your code into the process, you can patch the table to jump to your code instead.
See http://www.codeproject.com/KB/threads/completeinject.aspx for code showing how to inject a dll into another process.
I think: Approach 2 is impossible. Approaches 1-3 require dll, that is loaded into all processes, and approach 3 is "more right". I suppose searching windows by timer is not suite by some reasons?
I would go with the first option. You should be able to get away with only installing the hook for the main UI thread of the app you're monitoring, but if that doesn't work, even global CBT hooks aren't terribly resource intensive in my experience. Of course, you'll want your hook DLL to contain as little as possible other than the hook logic itself. If you need anything bulky, link it dynamically only when you know you're in the right process.