Hooking is Simple (Part 3)
“Another identical hooking library?” you would ask. “Identical but different,” I would answer. Deviare has some distinctive features making it different from both Detours and madCodeHook and making it much more useful in some cases.
The library is distributed under the double license: GPL\commercial.
For open source projects, it can be found on GitHub, and those who need support and the right to incorporate the library’s code into a mature product are welcome to the official website. That means, yes, you can simply read the library’s code, take it from GitHub and incorporate it into your open-source project right now without paying a dime to anyone. It is a miracle unavailable with Detours and madCodeHook. It should be mentioned that the project remained closed for a long time, but then Nektra decided to be somehow closer to the people.
The library makes the base for a powerful product SpyStudio
Before writing any code for hooking, you can simply start this utility and see what it is capable of. Detours and madCodeHook have also been used to make many things, but, surprisingly, no similar software has ever been developed by the authors of these libraries.
In their blog, the authors share a bunch of case studies about hooking
There you can find hooking for SQL Server to prevent SQL injections, video recording of games, created with the use of DirectX, cheats and modifying a player’s speed in a browser. When you read it, you quickly understand how hooking should be used.
Apart from the classical С++, COM component is offered that allows hooking from anywhere (C#, Python, VB, Delphi, etc.)
Yes, finally, hooking can be used without understanding the meaning of the reference to a reference to an array of references.
Not only native functions or COM objects but also .NET methods can be hooked.
This feature doesn’t seem such a “killer”, as .NET has never had big problems with metadata and reflection, and that means that those who needed it could do it themselves. Still, why not give zest to your “pie”?
The library has long lived through all “childhood” illnesses
Today, it is used by the Fortune 500, while the partnership with VMware allows, for example, making portable versions of installed applications.
I will not write miles of code (it’s useless for an open source library with examples on GitHub). I’ll just give some overview.
An injection of your library into a foreign process:
#include “NktHookLib.h”
NktHookLibHelpers::InjectDllByPidW(dwPid, L”myDll.dll”);
Hooking a function:
#include “NktHookLib.h”
typedef int (WINAPI *lpfnMessageBoxW)(__in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType);
static int WINAPI Hooked_MessageBoxW(__in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType);
static struct {
SIZE_T nHookId;
lpfnMessageBoxW fnMessageBoxW;
} sMessageBoxW_Hook = { 0, NULL };
int WinMainCRTStartup()
{
CNktHookLib cHookMgr;
HINSTANCE hUser32Dll;
LPVOID fnOrigMessageBoxW;
DWORD dwOsErr;
hUser32Dll=NktHookLibHelpers::GetModuleBaseAddress(L”user32.dll”);
if (hUser32Dll == NULL) {
::MessageBoxW(0, L”Error: Cannot get handle of user32.dll”, L”HookTest”, MB_OK|MB_ICONERROR);
return 0;
}
fnOrigMessageBoxW=NktHookLibHelpers::GetProcedureAddress(hUser32Dll, “MessageBoxW”);
if (fnOrigMessageBoxW == NULL) {
::MessageBoxW(0, L”Error: Cannot get address of MessageBoxW”, L”HookTest”, MB_OK|MB_ICONERROR);
return 0;
}
dwOsErr=cHookMgr.Hook(&(sMessageBoxW_Hook.nHookId),(LPVOID*)&(sMessageBoxW_Hook.fnMessageBoxW),
fnOrigMessageBoxW, Hooked_MessageBoxW,
NKTHOOKLIB_DisallowReentrancy);
::MessageBoxW(0, L”This should be hooked”, L”HookTest”, MB_OK);
dwOsErr = cHookMgr.Unhook(sMessageBoxW_Hook.nHookId);
::MessageBoxW(0, L”This should NOT be hooked”, L”HookTest”, MB_OK);
return 0;
}
static int WINAPI Hooked_MessageBoxW(__in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType)
{
return ::MessageBoxW(hWnd, lpText, L”HOOKED!!!”, uType);
}
Finally, somehow in this way, Notepad is started from Python where you hook the CreateFileW function:
import win32com.client
import ctypes, sys
from EventHandlers import NktSpyMgrEvents
from AuxFunctions import *
if sys.version_info.major < 3:
warnings.warn(“Need Python 3.0 for this program to run”, RuntimeWarning)
sys.exit(0)
win32com.client.pythoncom.CoInitialize()
spyManager=win32com.client.DispatchWithEvents(“DeviareCOM.NktSpyMgr”, NktSpyMgrEvents)
result = spyManager.Initialize()
if not result == 0:
print (“ERROR: Could not initialize the SpyManager. Error code: %d” % (result))
sys.exit(0)
notepad = StartNotepadAndHook(spyManager)
MessageBox = ctypes.windll.user32.MessageBoxW
MessageBox(None, “Press OK to end the demo.”, “Deviare Python Demo”, 0)
notepad.Terminate(0)
Good luck with the Deviare library!