Skip to content

Add Win32K input/hooking telemetry #708

Description

@rabbitstack

Motivation

Extend Fibratus's detection capabilities by collecting telemetry from the Microsoft-Windows-Win32K provider around window/input hooking and keyboard state APIs. These calls have high security value for detecting keylogging and input-surveillance techniques:

  • Enumerating keyboard key state from an unusual process
  • Attempts to install an application-defined hook procedure to monitor keystroke messages
  • Attempts to enumerate keystroke state via the DirectInput-style polling pattern
  • Attempts to register for raw keyboard input via RegisterRawInputDevices

Expectation

Fibratus gains four new event types mapped to the corresponding Win32K provider event IDs, each carrying the full set of documented parameters:

Event ID Fibratus event type Source API
1000 SetWinEventHook SetWinEventHook
1001 RegisterRawInputDevices RegisterRawInputDevices
1002 SetWindowsHook SetWindowsHookEx
1003 GetAsyncKeyState GetAsyncKeyState

Proposal

  • Start the Microsoft-Windows-Win32K ETW session with the AuditApiCalls keyword to gate the emission of the four events above
  • Parse each event's params via the ParamDecoder, consistent with existing event handling:
    • SetWinEventHook (1000)
      • min_event (uint32): low bound of the event range being hooked
      • max_event (uint32): high bound of the event range being hooked
      • pid (uint32): PID the hook is restricted to (0 = all processes)
      • tid (uint32): TID the hook is restricted to (0 = all threads)
      • flags (uint32): hook flags (e.g. WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS)
      • hook_instance (pointer/uint64): handle to the installed hook
    • RegisterRawInputDevices (1001)
      • status (bool/int32): success/failure of the registration call
      • usage_page (uint16): HID usage page (e.g. generic desktop controls)
      • usage (uint16): HID usage ID within the page (e.g. keyboard, mouse)
      • flags (uint32): registration flags (e.g. RIDEV_INPUTSINK, RIDEV_NOLEGACY)
      • target_window (pointer/uint64): target window handle receiving raw input
    • SetWindowsHook (1002)
      • filter_type (uint32): hook type (e.g. WH_KEYBOARD, WH_KEYBOARD_LL, WH_MOUSE)
      • module_path (string): path/name of the module containing the hook procedure
      • module_handle (pointer/uint64): handle to that module
      • filter_proc (pointer/uint64): address of the hook procedure
      • status (bool/int32): success/failure of installing the hook
    • GetAsyncKeyState (1003)
      • pid (uint32): process calling GetAsyncKeyState
      • millis_since_last_key_event (uint32/uint64): milliseconds elapsed since the last key event, useful for spotting tight polling loops typical of keyloggers
      • background_callcount (uint32): count of calls made while the process was not in the foreground, a strong signal for covert key-state polling

Additional context

  • GetAsyncKeyState's BackgroundCallCount/MsSinceLastKeyEvent pair is the strongest built-in signal here. Legitimate foreground apps rarely poll key state at high frequency while backgrounded, so this could support a simple threshold-based detection rule out of the box

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs: configIndicates the issue requires changes in the config file/flagsscope: events/telemetryAnything related to kernel eventstype: featureIntroduces a new functionality

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions