This is the second part of the DLL Injection series. For your convenience you can find other parts in the table of contents in Part 1 – Registry
Last time we saw how to inject DLL using registry. Today we are going to implement another approach using Hooks.
Hooks
Hooks allow us to execute a piece of code when specified type of message is sent to window. For instance, we might want to implement keylogger which would register all pressed keys without modifying them. Since there is an option to register global hook — e.g., hook which will execute in every process in the system — we can use this approach to inject our custom logic. Of course “every process in the system” means only processes which we can access easily, we will not overcome the UAC or hack system this way.
Code
Let’s assume that we have the following method:
1 2 3 4 |
extern "C" __declspec(dllexport) int kbhook(int code, WPARAM wParam, LPARAM lParam) { // Do something with keyboard message return CallNextHookEx(NULL, code, wParam, lParam); } |
We receive three arguments describing the message, do something with them, and finally call method CallNextHookEx
which passes the hook information to the next method in the hook chain. We need to compile this code and output DLL library. Let’s call it KeyboardHook.dll
. Now we can inject the routine using the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include "stdafx.h" #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { // Load library in which we'll be hooking our functions. HMODULE dll = LoadLibrary(L"KeyboardHook.dll"); if(!dll) { printf("The DLL could not be found.\n"); return -1; } // Get the address of the function inside the DLL./ HOOKPROC address = (HOOKPROC)GetProcAddress(dll, "kbhook"); if(!address) { printf("The function was not found.\n"); return -2; } // Hook the function. HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, address, dll, 0); if(!handle) { printf("The KEYBOARD could not be hooked.\n"); return -3; } printf("Program successfully hooked. Press enter to unhook the function and stop the program."); getchar(); // Unhook the function. UnhookWindowsHookEx(handle); return 0; } |
When we compile the code, put DLL into correct place (see “search order” in previous part), and execute it, we should successfully hook our code. To verify this, try to press any key on the keyboard and our code from DLL should execute. It should work across the processes, so it should execute when you type in notepad as well.
Summary
As we can see, this method is pretty easy. All we need to do is to prepare custom routine for handling Windows messages and execute a piece of code to register the hook. We are also able to inject the code into already started process. However, there are drawbacks: we do not control into which processes we inject our code (because it is injected into every program), we need to rely on windows messages what sometimes might be difficult (e.g., when passing a keyboard message to windows service), also anti-viruses sometimes blocks this method.