Background Message Interception Using Windows Hooks: A Practical Example

One of my favorite hobbies is playing computer games and streaming the gameplay using a web platform such as Amazon’s Twitch. I know, I know, it’s not very exciting to have a hobby related to computers if you already have to work with them on a daily basis, but believe it or not, streaming gameplays is actually a rising trend, with the most popular Twitch channels reporting millions of followers and views.
This trend has achieved such popularity that even Google is improving the YouTube platform to increase its streaming capabilities.

Usually, streamers like to play random sounds to enrich the experience for their viewers. For instance I love playing the infamous “toasty” clip from Mortal Kombat 2 whenever I kill another player in a game that has nothing to do with Mortal Kombat.

Of course, manually playing the sounds using a media player can be a very demanding task for someone who has both their hands already occupied playing a computer game. But how about we build a program that automatically plays the sounds we want whenever we press a key?

The first problem we have to deal with if we want to build such a program is to be able to handle keyboard input even if our program is not in focus (because most likely the game we’re currently playing will own the focus)   Fortunately for us, there is a technology which allows us to do just that.

Enter the Magic of Hooks

Hooking is a set of techniques that aim to expand the normal functionality of operating systems, applications and/or software components by intercepting the normal flow of messages, events and function calls. The functions that are executed in such interceptions are known as hooks, and they are used for many tasks, from debugging to benchmarking applications, and even in rootkits and game cheats such as wallhacks or aim triggers (which we won’t be covering here, I don’t think I can handle any more cheaters in my games!)

There are two ways to use hooks. One of them involves physically modifying the executable file or library of the desired application, to intercept its function calls and have them replaced with your own code. With this technique you would typically use a disassembler to find the entry point of a specific function and alter it to dynamically load some other library and then execute the methods inside that library. You could also alter the import table of an executable to achieve the same effect.
The second way to implement hooking is by runtime modification. Operating systems such as Windows or Linux provide ways to easily insert event hooks at runtime (if the application requesting the hook has the permission to do so) Let’s focus on what Microsoft Windows provides to us reading the definition of hooks in MSDN:

“A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure. ”

This is exactly what we need. We actually don’t need to disassemble any code and modify any libraries as the first technique requires, the only thing we want is whenever we press a key in our keyboard, capture that message, check if there is a sound assigned to that particular key, play the sound and finally send the message to the target window. Let’s take a look at the code.

Building the Program

We will be using the Win32API and the C++ programming  language, but don’t worry the actual code is very simple. You can compile it very easily using the de-facto IDE for Windows native applications: VisualStudio and including the proper libraries.

That’s it. The ReadConfigFile function parses a text file that associates a virtual key code with a specific sound file path loading that information into an std::map<int, std::wstring> container. The last missing part of this small puzzle is our own implementation of the LowLevelKeyboardProc hook which we transcribe here:

Don’t forget to include the mmsystem.h header and winmm.lib library to use the PlaySound function. It’s worth nothing that these type of hooks tend to slow down the system because they increase the amount of processing the system must perform for each message. Microsoft advices to install a hook only when necessary and remove it as soon as possible. Fortunately our program is so simple that the system’s performance won’t be affected at all.

And we’re done. Building the program by ourselves probably took us less time than googling a freeware virus-free application that does the same task uh?