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:
- linux-usb-gadgets / gt https://github.com/linux-usb-gadgets/gt
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.
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
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
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
doneHID 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#!/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 0USBMODE payloads should always wait for enumeration before sending input, and should provide clear LED feedback to indicate state transitions.