Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
logitech-ipc-protocol — Reverse-engineered Logi Options+ agent IPC protocol. Switch Logitech multi-host devices programmatically via Unix socket (macOS) or named pipe (Windows). | Kitploit
Tools/GitHubGitHub/saimanish1/logitech-ipc-protocol
Embedded Systems SecurityBluetooth SecurityReverse EngineeringWireless SecurityHardware HackingHardware & IoT SecurityPapers & ResearchLearning & Education
GitHubsaimanish1/logitech-ipc-protocol

logitech-ipc-protocol

Reverse-engineered Logi Options+ agent IPC protocol. Switch Logitech multi-host devices programmatically via Unix socket (macOS) or named pipe (Windows).

View Repository
1724 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

logitech-ipc-protocol

Reverse-engineered documentation of the Logi Options+ agent IPC protocol. Enables programmatic control of Logitech multi-host devices (host switching, device queries) without raw HID access, on both macOS and Windows.

The protocol has not been publicly documented before this project.

Problem

macOS blocks raw HID access to Bluetooth input devices at the kernel level. No permissions, entitlements, or hacks bypass this. The Logi Options+ agent has Apple-signed entitlements (com.apple.security.device.bluetooth) that grant it Bluetooth HID access. This project communicates with the agent through its IPC channel instead.

Files

FileDescription
logi-options-ipc-reverse-engineering.mdFull reverse engineering chronicle
software-kvm-setup.mdTwo-way software KVM setup guide (Windows + Mac)
switch_to_windows.pyMac-side script that switches Logitech devices and monitor input via Unix socket IPC
api-reference.mdAgent API reference: working endpoints, protobuf types, device capabilities
kvm.ahkAutoHotkey v2 script: Win+1/2/3 hotkeys that call kvm_daemon_windows.py --switch (runs in system tray)
kvm_daemon_windows.pyWindows device switching via named pipe, monitor switching via DDC/CI
kvm_config.iniWindows configuration (hotkeys, monitor inputs)
query_feature_index.pyDiscovers HID++ ChangeHost feature index for Logitech devices (Windows)
query_agent_windows.pyQueries the agent on Windows via named pipe
config.iniLegacy UnifiedSwitch configuration (superseded by kvm_daemon_windows.py)

Usage

Mac

root@kitploit:~
python3 switch_to_windows.py 0        # Switch to host 0 (DisplayPort)
python3 switch_to_windows.py 1        # Switch to host 1 (HDMI)
python3 switch_to_windows.py --dry-run 0  # Show what would happen

Requires Logi Options+ running and m1ddc installed (brew install m1ddc).

Windows

root@kitploit:~
# Start the AHK hotkey listener (runs in system tray, no console)
# Requires AutoHotkey v2: winget install AutoHotkey.AutoHotkey
start kvm.ahk

# Or switch directly from the command line
python kvm_daemon_windows.py --switch 1

# Show discovered devices and configured hotkeys without switching
python kvm_daemon_windows.py --dry-run

Requires Logi Options+ running. Install dependencies: pip install pywin32.

The AHK script listens for Win+1/2/3 and calls kvm_daemon_windows.py --switch N for each. The Python script discovers devices from the agent automatically (no hardcoded device IDs or HID paths). Edit kvm_config.ini to configure hotkeys and monitor DDC/CI input values.

Protocol

The agent listens on:

  • macOS: Unix domain socket at /tmp/logitech_kiros_agent-<hash>
  • Windows: Named pipe at \\.\pipe\logitech_kiros_agent-<hash>

Same wire protocol on both platforms. Binary frame format:

root@kitploit:~
LE32(total_len) + BE32(proto_name_len) + "json" + BE32(msg_len) + JSON_message

Switch a device to a different host:

root@kitploit:~
{
  "msg_id": "1",
  "verb": "SET",
  "path": "/change_host/<device_id>/host",
  "payload": {
    "@type": "type.googleapis.com/logi.protocol.devices.ChangeHost",
    "host": 0
  }
}

The payload is a google.protobuf.Any field serialized as inline JSON with an @type annotation. The agent uses a strict protobuf JSON parser; unknown fields cause INVALID_MESSAGE_RECEIVED.

Requests use msg_id (snake_case). Responses use msgId (camelCase). Verbs are strings: "GET", "SET", "SUBSCRIBE", "BROADCAST".

See logi-options-ipc-reverse-engineering.md for the full protocol documentation.

IPC error handling

For long-running automation, reconnect on BrokenPipeError and re-discover the socket/pipe path.

Windows HID++ gotchas

These apply when sending HID++ commands directly, not through the agent. kvm_daemon_windows.py avoids all of them by going through the agent's named pipe.

Legacy HID++ gotchas (for direct HID access)

HID++ collection varies per device. The MX Master 3S exposes HID++ on COL02. The MX Keys S uses COL05. Both use usage page FF43:0202. Verify with:

root@kitploit:~
Get-PnpDeviceProperty -InstanceId "<instance_id>" -KeyName DEVPKEY_Device_HardwareIds
# Look for UP:FF43_U:0202

Feature indices differ per device. ChangeHost (0x1814) is at index 0x0A on MX Keys S but 0x09 on MX Mechanical. Query at runtime via IRoot::GetFeature:

root@kitploit:~
Send: {0x11, 0x00, 0x00, 0x0D, 0x18, 0x14, ...}  (20 bytes)
Read: response byte 4 = feature index

Device re-pairing changes HID paths. Switching from Bolt receiver to direct BT LE changes the path entirely. Run query_agent_windows.py to get current paths from the agent.

BT LE GATT vendor collection goes "Unknown." Windows occasionally fails to initialize the HID++ GATT service. The device works normally but the vendor command channel is dead. Fix: toggle Bluetooth off/on in Windows Settings. This is a Windows/firmware issue.

Tested versions

VersionStatus
Logi Options+ 2.0.840907Working (macOS Tahoe, Windows 11)

The wire protocol and core API paths (/devices/list, /change_host/<id>/host) have been stable. Device re-pairing broke HID paths and collection numbers but the IPC protocol itself was unaffected.

Disclaimer

This project is for educational and research purposes only. It documents an undocumented, unsupported protocol that Logitech can change or remove at any time. The authors are not responsible for any damage, data loss, bricked devices, or broken functionality resulting from use of this code or documentation. Use at your own risk.

This project is not affiliated with or endorsed by Logitech.

License

MIT

Download Tool
ScenarioWhat happensDetection
Agent not runningSocket/pipe doesn't existconnect() raises FileNotFoundError or ConnectionRefusedError
Agent restarts mid-sessionConnection breakssend() raises BrokenPipeError; recv() returns empty
Device on another hostNO_SUCH_PATHCheck result.code
Device unreachableTIMEOUT after ~3sCheck result.code
Malformed payloadINVALID_MESSAGE_RECEIVEDMissing @type or unknown fields
Socket hash changesOld path goneAlways discover dynamically, never hardcode
Stale socket after restartConnectionRefusedErrorRetry after short delay
Concurrent clientsWorks fineAgent handles multiple connections