Hooks for mouse - limitations and performance - c++

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.

Related

Trying to hook to MessageBeep system API

I've been asked by a client to solve the following pesky issue. They have a custom software that has a tendency of displaying message boxes "left and right" without any apparent reason. For instance, the software itself is an accounting program, and when they take a customer's payment, the message box may be displayed about 3 or 4 times in a row. Each message box plays Windows default sound. Unfortunately the way this software was programmed, the type of sounds it plays is completely wrong. For instance, it may display a warning message box and play the warning system sound when the message itself is just an information. All this is quite annoying for the staff who uses the software.
I tried to contact the vendor who distributes the software, but I hit a deadend with them. So now I am looking for ways to mitigate this issue.
My easiest solution was to suggest to mute the speakers, but unfortunately, they require sound to be present to be able to hear incoming emails, and most importantly, be able to play voice mail from them later. So my solution was to somehow mute message box sounds just for a single process.
From my experience, I know that there're two APIs that may be producing these sounds: MessageBeep and an older Beep.
I also found this article that explains how to use AppInit_DLLs to hook to system APIs. It works great, except that both of the APIs that I need to hook to come from User32.dll and not from kernel32.dll like the author suggests.
There's also this post in the questions section that kinda gives approximate steps to hooking to an API from User32.dll, but when I tried to implement them, there's not enough information (for my knowledge to do it.)
So my questions is, does anyone know how to hook to an API in the User32.dll module?
EDIT: PS. Forgot to mention. This software is installed on Windows 7 Professional, with UAC disabled -- because it is not compatible with UAC :)
As an alternative you can patch you application. Find calls to MessageBeep and overwrite them with nop.
This is the hard way of doing it: if your app is supposed to be running as Administrator on a pre-Vista Windows, you could get the address of the API via ::GetProcAddress(), give yourself privileges to write to its memory page, and overwrite the beginning of the API's code with a "jmp" assembly instruction jumping into the address of your override function. Make sure your overwrite function takes the same arguments and is declared as __cdecl.
Expanded answer follows.
The "standard" technique for API hooking involves the following steps:
1: Inject your DLL into the target process
This is usually accomplished by first allocating memory in the target process for a string containing the name/path of your DLL (e.g. "MyHook.dll"), and then creating a remote thread in the target process whose entry point is kernel32::LoadLibraryA() passing the name of your DLL as argument. This page has an implementation of this technique. You'll have to wrestle a bit with privileges, but it's guaranteed to work 100% on Windows XP and earlier OSes. I'm not sure about Vista and post-Vista, Address Space Layout Randomization might make this tricky.
2. Hook the API
Once your DLL is loaded into the target process, its DllMain() will be executed automatically, giving you a chance to run anything you want in the target process. From within your DllMain, use ::LoadLibraryA() to get the HMODULE of the library containing the API you want to hook (e.g. "user32.dll") and pass it to ::GetProcAddress() together with the name of the API you want to hook (e.g. "MessageBeep") to get the address of the API itself. Eventaully give yourself privileges to write to that address' page, and overwrite the beginning of the API with a jmp instruction jumping into your detour (i.e. into your "version" of the API to hook). Note that your detour needs to have the same signature and calling convention (usually _cdecl) as the API you want to hook, or else monsters will be awakened.
As described here, this technique is somewhat destructive: you can't call back into the original API from the detour, as the original API has been modified to jump into yours and you'll end up with a very tight and nice infinite loop. There are many different techniques that would allow you to preserve and/or call back into the original API, one of which is hooking the ...A() versions of the API and then calling into the ...W() versions (most if not all of the ...A() Windows API's convert ASCII strings into UNICODE strings and end up calling into their ...W() counterparts).
No need to spend time on a custom program to do this.
You can mute a particular application when it's running, and that setting will be remembered the next time you open the application. See https://superuser.com/questions/37281/how-to-disable-sound-of-certain-applications.
There's also the Windows Sound Sentry that will turn off most system sounds, although I'm not aware of any per-application settings for Sound Sentry.
You can use Deviare API hook and solve the hook in a couple of C# lines. Or you can use EasyHook that is a bit more difficult and less stable.

Keyboard hook only working in the calling process

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.

Detecting child processes

Is there a way (in C++ & windows XP) to detect if one process spawns any other processes?
for example,
write.exe in system32 spawns wordpad.exe then disappears, is there a function that tells me if the process is about to do this?
for those interested i solved the problem using this section of msdn:
http://msdn.microsoft.com/en-us/library/aa390425(v=VS.85).aspx
Nothing in the Win32 API for this. However, it is supported through WMI with the Win32_ProcessStartTrace query. You'll find some C# code that demonstrates the query in my answer in this thread. Writing WMI code in C++ is fairly painful, you'll find a link to boilerplate code you have to write in the MSDN Library article.
Do beware that this isn't particularly fast. It isn't clear to me how much help the WMI provider gets from the kernel to generate the notification but given the speed it quacks like polling. In other words, the process is likely to be well on its way by the time you get the notification. This is otherwise par for the course on a multitasking operating system.
You can enumerate over the process tree, which identifies running processes and their parents. This is the inverse of what you want (you want to identify child processes, not parent processes). But of course by keeping track of parent process IDs while enumerating, you can identify which sub-processes a given process has spawned.
To do this, call CreateToolhelp32Snapshot and then use Process32First and Process32Next to enumerate the processes. The enumeration will fill in a PROCESSENTRY32 struct that contains a th32ParentProcessID member.
This is a polling method; there may be another way of actually hooking the CreateProcess function, but I don’t have any information about that.
I think you would need to make a global hook DLL that attaches itself to every running process. DLL then finds a place where a function call to CreateProcess is mapped to actual CreateProcess from kernel32, and change a table entry to redirect the call to it's own code to "detect" the call to CreateProcess. All this assuming that some user firewall will not prevent your global hook from executing.

How can I detect message boxes popping up in another process?

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.

How do I intercept messages being sent to a window?

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