Installing a remote hook using EasyHook with C++
In this tutorial we will use a hook similar to what we created in Using EasyHook with C++, and inject it into another process. We will also pass through the desired frequency offset entered by the user and use this in the myBeepHook
hook within the target application.
In this tutorial we will create 3 projects within the same solution:
- A console app “Target” that will be used as the target of our hook. This will simply call the Win32 Beep function whenever the [enter] key is pressed.
- A console app “Injector” that will act as the injector of “BeepHook.dll” into the target application “Target.exe”. This application contains our injection logic, including asking the user for the process Id of the target application, and the frequency to be added to the
Beep
call within the hook. - A native DLL “BeepHook.dll” that we will inject into the target console app “Target.exe” above, this will contain our hooking logic and the necessary export to support EasyHook injection.
The full NativeRemoteHook tutorial source project can be found here.
The target application
We will begin by creating a new Win32 Console Application project called “Target”. This app will output the current process Id, and then await user input before calling the Win32 Beep function.
The injector application
The injector is a new Win32 Console Application project called “Injector”. This is often also referred to as the host application and will be responsible for injecting a DLL into the target application.
This app will ask for the target process Id, then the frequency by which we want to change the sound of calls to Beep
within the target process. These are then passed into a call to EasyHook’s RhInjectLibrary
function along with the location of the 32-bit DLL to be injected.
Install the EasyHook Native Package from NuGet (you will see more than one package if you search for EasyHook, you are after the “EasyHook Native Package”). Alternatively you can download the EasyHook binary package and manually reference the EasyHook library and “easyhook.h” (see Manually adding EasyHook to your C++ project).
If targeting 64-bit applications it would be necessary to provide a 64-bit DLL to be injected. Note: unlike the managed EasyHook library the native injection method does not support crossing the Wow64 boundary, therefore your injector app and injection DLL must be compiled for 32-bit and/or 64-bit as required.
Depending on how you configure the outputs of your projects, you may need to adjust the path to “BeepHook.dll”. Just remember that the process’ current directory will be different when running within the Visual Studio debugger as compared to when it is run directly from Windows Explorer or the Command Prompt.
The hook DLL
The hook DLL is a new Win32 Project called “BeepHook”, select “DLL” as the Application type within the new project wizard. This project will not only contain the hook logic, but also the entry point that EasyHook requires to support injecting the native DLL.
Install the EasyHook Native Package from NuGet (you will see more than one package if you search for EasyHook, you are after the “EasyHook Native Package”). Alternatively you can download the EasyHook binary package and manually reference the EasyHook library and “easyhook.h” (see Manually adding EasyHook to your C++ project).
We will create the myBeepHook
function as defined within “Using EasyHook with C++”, except that this time we will allow the frequency to be configured using a global frequency offset that has been provided by the injector application.
For remote native/unmanaged hooks, EasyHook is expecting to find an export named NativeInjectionEntryPoint
within your DLL. EasyHook will call this method once the DLL has successfully been injected. This is also where we will install our myBeepHook
hook function.
Our hook will be installed in almost the exact same way as shown previously aside from one important change, we will be setting up the thread ACL to include ALL threads EXCEPT the injector thread. This means that all threads that call Beep
will call our hook function except the thread that called NativeInjectionEntryPoint
(i.e. the injection thread).
Another difference in this tutorial is that we will not be uninstalling the hook. Instead we will leave it running until the target process exits.
Running the example
To run the example scenario follow these steps:
- Ensure all projects have been built for 32-bit.
- Start up Target.exe (either in the debugger or directly) - note that it outputs the process Id to be used.
- Press enter to hear the beep.
- Start Injector.exe
- Enter the process Id for Target.exe
- Enter a frequency to change the beeps by, e.g. 800
- If all is well you should see a message indicated that the library was successfully injected.
- Otherwise you will see EasyHook’s reason why it failed (e.g. could not find the DLL or process not found etc…).
- Back within the Target.exe console app you should see some text output by the injected DLL
- Pressing enter should now play the beep using a frequency offset by the value passed in.
Included below is some example output from each application.
The Injector application:
The Target application: