Skip to Content

USBMODE

This page documents USBMODE payload examples for Lichee-Jack.

USBMODE controls how Lichee-Jack presents itself to a host computer over USB by configuring the Linux USB gadget stack via configfs.

It enables Lichee-Jack to dynamically appear as different USB devices such as:

  • Ethernet adapters
  • HID keyboards or mice
  • USB mass storage devices
  • Composite devices combining multiple functions

gt

The Lichee-Jack utility USBMODE uses the gt CLI tool from the upstream project:

gt loads declarative scheme files that describe a complete USB gadget layout, including device descriptors, functions, and configurations.

Each scheme is applied atomically, making USBMODE switching predictable and reversible.

Scheme examples

The following examples show common gadget layouts used by USBMODE payloads.

DEBUG

DEBUG mode exposes a USB network interface using NCM. This is typically used for development, debugging, and interactive access.

/root/config/gt/templates/debug.scheme
attrs : { bcdUSB = 0x200; idVendor = 0x1D6B; idProduct = 0x6d99; }; strings = ( { lang = 0x409; manufacturer = "KALIASSISTANT"; product = "LICHEE-JACK V1.0 SharkJack/LANTap (DEBUG MODE)"; serialnumber = "00000000000000000000000000000000"; } ); functions : { ncm_usb0 : { instance = "usb0"; type = "ncm"; attrs : { dev_addr = "42:61:64:ab:cc:69"; host_addr = "48:6f:73:0f:56:90"; }; }; }; configs = ( { id = 1; name = "c"; attrs : { bmAttributes = 0x80; bMaxPower = 250; }; functions = ( { name = "ncm.usb0"; function = "ncm_usb0"; }); } );

HID

HID mode presents Lichee-Jack as a USB keyboard and mouse device.

This mode is commonly used for:

  • Keystroke injection
  • Mouse movement or click automation
  • Human interface emulation payloads
/root/config/gt/templates/hid.scheme
attrs : { bcdUSB = 0x200; idVendor = 0x1D6B; idProduct = 0x6d99; }; strings = ( { lang = 0x409; manufacturer = "KALIASSISTANT"; product = "LICHEE-JACK V1.0 SharkJack/LANTap (HID MODE)"; serialnumber = "00000000000000000000000000000000"; } ); functions : { hid_keyboard0 : { instance = "keyboard0"; type = "hid"; attrs : { protocol = 1; subclass = 1; report_length = 8; report_desc = ( 0x05,0x01, # USAGE_PAGE (Generic Desktop Ctrls) 0x09,0x06, # USAGE (Keyboard) 0xa1,0x01, # COLLECTION (Application) 0x05,0x08, # USAGE_PAGE (LEDs) 0x19,0x01, # USAGE_MINIMUM (Num Lock) 0x29,0x03, # USAGE_MAXIMUM (Scroll Lock) 0x15,0x00, # LOGICAL_MINIMUM (0) 0x25,0x01, # LOGICAL_MAXIMUM (1) 0x75,0x01, # REPORT_SIZE (1) 0x95,0x03, # REPORT_COUNT (3) 0x91,0x02, # OUTPUT (Data,Var,Abs, No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x09,0x4b, # USAGE (Generic Indicator) 0x95,0x01, # REPORT_COUNT (1) 0x91,0x02, # OUTPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95,0x04, # REPORT_COUNT (4) 0x91,0x01, # OUTPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x05,0x07, # USAGE_PAGE (Kbrd/Keypad) 0x19,0xe0, # USAGE_MINIMUM (0xe0) 0x29,0xe7, # USAGE_MAXIMUM (0xe7) 0x95,0x08, # REPORT_COUNT (8) 0x81,0x02, # INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75,0x08, # REPORT_SIZE (8) 0x95,0x01, # REPORT_COUNT (1) 0x81,0x01, # INPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x19,0x00, # USAGE_MINIMUM (0x00) 0x29,0x91, # USAGE_MAXIMUM (0x91) 0x26,0xff,0x00, # LOGICAL_MAXIMUM (255) 0x95,0x06, # REPORT_COUNT (6) 0x81,0x00, # INPUT (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xc0 # END_COLLECTION ); }; }; hid_mouse_relative : { instance = "mouse_relative"; type = "hid"; attrs : { protocol = 0; subclass = 0; report_length = 7; report_desc = ( 0x05,0x01, # USAGE_PAGE (Generic Desktop) 0x09,0x02, # USAGE (Mouse) 0xa1,0x01, # COLLECTION (Application) # 8-buttons 0x05,0x09, # USAGE_PAGE (Button) 0x19,0x01, # USAGE_MINIMUM (Button 1) 0x29,0x08, # USAGE_MAXIMUM (Button 8) 0x15,0x00, # LOGICAL_MINIMUM (0) 0x25,0x01, # LOGICAL_MAXIMUM (1) 0x95,0x08, # REPORT_COUNT (8) 0x75,0x01, # REPORT_SIZE (1) 0x81,0x02, # INPUT (Data,Var,Abs) # x,y relative coordinates 0x05,0x01, # USAGE_PAGE (Generic Desktop) 0x09,0x30, # USAGE (X) 0x09,0x31, # USAGE (Y) 0x15,0x81, # LOGICAL_MINIMUM (-127) 0x25,0x7f, # LOGICAL_MAXIMUM (127) 0x75,0x08, # REPORT_SIZE (16) 0x95,0x02, # REPORT_COUNT (2) 0x81,0x06, # INPUT (Data,Var,Rel) # vertical wheel 0x09,0x38, # USAGE (wheel) 0x15,0x81, # LOGICAL_MINIMUM (-127) 0x25,0x7f, # LOGICAL_MAXIMUM (127) 0x75,0x08, # REPORT_SIZE (8) 0x95,0x01, # REPORT_COUNT (1) 0x81,0x06, # INPUT (Data,Var,Rel) # horizontal wheel 0x05,0x0c, # USAGE_PAGE (Consumer Devices) 0x0a,0x38,0x02, # USAGE (AC Pan) 0x15,0x81, # LOGICAL_MINIMUM (-127) 0x25,0x7f, # LOGICAL_MAXIMUM (127) 0x75,0x08, # REPORT_SIZE (8) 0x95,0x01, # REPORT_COUNT (1) 0x81,0x06, # INPUT (Data,Var,Rel) 0xc0 # END_COLLECTION ); }; }; hid_mouse_absolute : { instance = "mouse_absolute"; type = "hid"; attrs : { protocol = 0; subclass = 0; report_length = 7; report_desc = ( 0x05,0x01, # USAGE_PAGE (Generic Desktop) 0x09,0x02, # USAGE (Mouse) 0xa1,0x01, # COLLECTION (Application) # 8-buttons 0x05,0x09, # USAGE_PAGE (Button) 0x19,0x01, # USAGE_MINIMUM (Button 1) 0x29,0x08, # USAGE_MAXIMUM (Button 8) 0x15,0x00, # LOGICAL_MINIMUM (0) 0x25,0x01, # LOGICAL_MAXIMUM (1) 0x95,0x08, # REPORT_COUNT (8) 0x75,0x01, # REPORT_SIZE (1) 0x81,0x02, # INPUT (Data,Var,Abs) # x,y relative coordinates 0x05,0x01, # USAGE_PAGE (Generic Desktop) 0x09,0x30, # USAGE (X) 0x09,0x31, # USAGE (Y) 0x15,0x00, # LOGICAL_MINIMUM (0) 0x26,0xff,0x7f, # LOGICAL_MAXIMUM (65535) 0x75,0x10, # REPORT_SIZE (16) 0x95,0x02, # REPORT_COUNT (2) 0x81,0x02, # INPUT (Data,Var,RAbs) # vertical wheel 0x09,0x38, # USAGE (wheel) 0x15,0x81, # LOGICAL_MINIMUM (-127) 0x25,0x7f, # LOGICAL_MAXIMUM (127) 0x75,0x08, # REPORT_SIZE (8) 0x95,0x01, # REPORT_COUNT (1) 0x81,0x06, # INPUT (Data,Var,Rel) # horizontal wheel 0x05,0x0c, # USAGE_PAGE (Consumer Devices) 0x0a,0x38,0x02, # USAGE (AC Pan) 0x15,0x81, # LOGICAL_MINIMUM (-127) 0x25,0x7f, # LOGICAL_MAXIMUM (127) 0x75,0x08, # REPORT_SIZE (8) 0x95,0x01, # REPORT_COUNT (1) 0x81,0x06, # INPUT (Data,Var,Rel) 0xc0 # END_COLLECTION ); }; }; }; configs = ( { id = 1; name = "c"; attrs : { bmAttributes = 0x80; bMaxPower = 250; }; functions = ( { name = "hid.keyboard0"; function = "hid_keyboard0"; }, { name = "hid.mouse_relative"; function = "hid_mouse_relative"; }, { name = "hid.mouse_absolute"; function = "hid_mouse_absolute"; }); });

The HID report descriptors fully define keyboard, relative mouse, and absolute mouse behavior.

UMS

UMS (USB Mass Storage) mode exposes a backing file as a removable disk to the host.

Typical use cases include:

  • Dropping files onto a target system
  • Delivering payloads or documents
  • Covert data staging
/root/config/gt/templates/ums.scheme
attrs : { bcdUSB = 0x200; idVendor = 0x1D6B; idProduct = 0x6d99; }; strings = ( { lang = 0x409; manufacturer = "KALIASSISTANT"; product = "LICHEE-JACK V1.0 SharkJack/LANTap (UMS MODE)"; serialnumber = "00000000000000000000000000000000"; } ); functions : { mass_storage : { instance = "ums0"; type = "mass_storage"; attrs : { stall = 1; luns = ( { cdrom = 0; ro = 0; removable = 1; nofua = 0; file = "/root/udisk.d/udisk.img"; } ); }; }; }; configs = ( { id = 1; name = "c"; attrs : { bmAttributes = 0x80; bMaxPower = 250; }; functions = ( { name = "mass_storage.ums0"; function = "mass_storage"; }); } );

Payload examples

Wait for host enumeration

Before interacting with the host, payloads should wait until the USB gadget is fully configured.

while [ "$(cat /sys/class/udc/*/state)" != "configured" ]; do sleep 1 done

HID payload

This example demonstrates a simple HID keystroke injection payload using Python.

Install the dependency on Lichee-Jack:

pip3 install zero-hid --break-system-packages
rr
#!/bin/bash cat > /tmp/hidpayload.py << "EOF" from zero_hid import Keyboard, KeyCodes from time import sleep with Keyboard() as k: k.press([KeyCodes.MOD_LEFT_GUI], KeyCodes.KEY_R) sleep(2) k.type("curl ascii.live/rick") sleep(2) k.press([], KeyCodes.KEY_ENTER) sleep(2) EOF USBMODE HID LED -c FFFF00 -lds 100000 while [ "$(cat /sys/class/udc/*/state)" != "configured" ]; do sleep 1 done sleep 0.5 LED -c FF0000 -lbs 50000 python3 /tmp/hidpayload.py LED -c 00FF00 -lds 500000 exit 0

USBMODE payloads should always wait for enumeration before sending input, and should provide clear LED feedback to indicate state transitions.

Last updated on