# Encoding A key event is encoded using two bytes, one for the event key, then one for the event modifier. If there are several event modifiers, they're combined using bitwise or. Note that a single modifier used on its own is encoded using a dedicated key for that edge case. TAB: 0x2b 0x00 CTRL TAB: 0x2b 0x01 CTRL ALT TAB: 0x2b 0x05 CTRL: 0xe0 0x00 Given that 0x00 isn't a valid key press in the USB HID standard (it means that no key has been pressed), it's used to encode delays. A delay sets the first byte to zero and the second byte to the delay. Delays exceeding 0xff are encoded by encoding the remaining delay in the same manner. DELAY 0: 0x00 0x00 (optimization opportunity here) DELAY 200: 0x00 0xc8 DELAY 400: 0x00 0xff 0x00 0x91 # Terms Key combination: A key press with optional modifiers HID symbol: The USB HID name for a key/modifier Modifiers: List of USB HID names corresponding to modifier keys Modifier masks: Numerical equivalent of modifiers list Modifier byte: Bitwise or combination of modifier masks Key symbol: List of USB HID names corresponding to non-modifier keys Key byte: Numerical equivalent of key sym Key combination bytes: Key byte followed by modifier byte Key sequence: Sequence of one or more key combinations # Example key combination: "TAB" normalized: "TAB" hid symbols: ("KEY_TAB") modifiers: () mod masks: () mod byte: #x00 key sym: "KEY_TAB" key byte: #x2b key combination bytes: (#x2b #x00) key combination: "CTRL-TAB" normalized: "CTRL TAB" hid symbols: ("KEY_MOD_LCTRL" "KEY_TAB") modifiers: ("KEY_MOD_LCTRL") mod masks: (#x01) mod byte: #x01 key sym: "KEY_TAB" key byte: #x2b key combination bytes: (#x2b #x01) key combination: "CTRL-ALT TAB" normalized: "CTRL ALT TAB" hid symbols: ("KEY_MOD_LCTRL" "KEY_MOD_LALT" "KEY_TAB") modifiers: ("KEY_MOD_LCTRL" "KEY_MOD_LALT") mod masks: (#x01 #x04) mod byte: #x05 key symbol: "KEY_TAB" key byte: #x2b key combination bytes: (#x2b #x05) key combination: "CTRL" normalized: "CTRL" hid symbols: ("KEY_LEFTCTRL") modifiers: () mod masks: () mod byte: #x00 key sym: "KEY_LEFTCTRL" key byte: #xe0 key combination bytes: (#xe0 #x00) # Compilation stages - Tokenization (`--keep=tokens`) - Parsing (`--keep=ast`) - Interpretation (`--keep=symbols`) - Translation - To binary (`--compact`) - To C (default) # Decompilation Goal: Compiling the decompilation output should produce the same input. - Invert lookup hash tables - Chop byte sequence into pairs - Identify key combination/delay - Reconstruct key combination - Identify modifier bytes - Look up modifier symbols, chop off "KEY_" - Identify key byte - Look up key symbol, chop off "KEY_" - Reconstruct delay - Fold successive delays into a larger one - Reconstruct (dead) key sequences - Trie might be useful for this, but probably not worth it (dead keys are used for non-US payloads which are rare) - Recognize string (delay) sequences - Fold as many single character keys without modifiers - Recognize repetition - This could be tricky, might require several passes with increasing windows (what's a reasonable max window size, the max string size encountered?) - Alternatively this should be performed on reconstructed commands, as only a command can be repeated...