Using EasyHook with C++
In this tutorial we will use EasyHook to hook the Win API Beep function. Whenever a call to Beep
is made we will increase the frequency originally passed in by 800hz.
Preparation:
- Create a new C++ console app
- Install the EasyHook Native Package from NuGet (you will see more than one package if you search for EasyHook, you are after only 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).
- Adding
#include <easyhook.h>
will allow us to call the EasyHook functions.
With our sample we will be demonstrating how to do the following:
- Retrieve the address of the original function.
- Gain an understanding of the original function’s parameters and calling convention.
- Prepare a replacement function that has the same number and type of parameters, as well as the same calling convention as the original function.
- We will use LhInstallHook to create the hook by adding a trampoline to the start of the original method. We will also uninstall the hook once we are done with it.
The complete example can be found at the end of this post.
Retrieving the original address
There are many ways to determine the correct address for a function, for this example we will assume that the function has been exported from another DLL and we will retrieve the address using GetProcAddress
.
An understanding of the original parameters / calling convention
By taking a look at the declaration within the Windows API we can see that the function Beep
looks like:
From this we can see that the function will return a BOOL
, that the calling convention is set to WINAPI
(which will be __stdcall
), and the function receives two DWORD
parameters as input.
Our replacement function is therefore going to look like:
Write the hook handler code
Our hook handler is going to simply intercept the call to Beep
and then call the original function while adding 800 to the frequency supplied.
Installing and uninstalling the hook handler
Now we can install our hook handler using LhInstallHook
. After installing the hook we also tell enable the hook handler for the current thread.
We keep a reference to the hook using a HOOK_TRACE_INFO
structure. This allows us to set-up the access control list (ACL) for which threads will be intercepted and which will continue unchanged - this can also be changed at a later time as needed. The ACLs can be configured as inclusive or exclusive with a call to LhSetInclusiveACL
and LhSetExclusiveACL
respectively.
Once we are finished with a hook then we can disable the hook with a call to LhUninstallHook
. This does not remove the trampoline, however the trampoline code will see that the hook is no longer active and continue back to the original function without using any handler. To restore the function to its original state before the trampoline was installed we can use LhWaitForPendingRemovals
.
Full Example
Here is the full example: