Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BadUSB: Mouse control #4004

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions applications/main/bad_usb/helpers/bad_usb_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,31 @@ bool hid_usb_kb_release(void* inst, uint16_t button) {
return furi_hal_hid_kb_release(button);
}

bool hid_usb_mouse_press(void* inst, uint8_t button) {
UNUSED(inst);
return furi_hal_hid_mouse_press(button);
}

bool hid_usb_mouse_release(void* inst, uint8_t button) {
UNUSED(inst);
return furi_hal_hid_mouse_release(button);
}

bool hid_usb_mouse_scroll(void* inst, int8_t delta) {
UNUSED(inst);
return furi_hal_hid_mouse_scroll(delta);
}

bool hid_usb_mouse_move(void* inst, int8_t dx, int8_t dy) {
UNUSED(inst);
return furi_hal_hid_mouse_move(dx, dy);
}

bool hid_usb_mouse_release_all(void* inst) {
UNUSED(inst);
return furi_hal_hid_mouse_release(0);
}

bool hid_usb_consumer_press(void* inst, uint16_t button) {
UNUSED(inst);
return furi_hal_hid_consumer_key_press(button);
Expand All @@ -51,6 +76,7 @@ bool hid_usb_release_all(void* inst) {
UNUSED(inst);
bool state = furi_hal_hid_kb_release_all();
state &= furi_hal_hid_consumer_key_release_all();
state &= hid_usb_mouse_release_all(inst);
return state;
}

Expand All @@ -67,6 +93,10 @@ static const BadUsbHidApi hid_api_usb = {

.kb_press = hid_usb_kb_press,
.kb_release = hid_usb_kb_release,
.mouse_press = hid_usb_mouse_press,
.mouse_release = hid_usb_mouse_release,
.mouse_scroll = hid_usb_mouse_scroll,
.mouse_move = hid_usb_mouse_move,
.consumer_press = hid_usb_consumer_press,
.consumer_release = hid_usb_consumer_release,
.release_all = hid_usb_release_all,
Expand Down Expand Up @@ -157,6 +187,27 @@ bool hid_ble_kb_release(void* inst, uint16_t button) {
return ble_profile_hid_kb_release(ble_hid->profile, button);
}

bool hid_ble_mouse_press(void* inst, uint8_t button) {
BleHidInstance* ble_hid = inst;
furi_assert(ble_hid);
return ble_profile_hid_mouse_press(ble_hid->profile, button);
}
bool hid_ble_mouse_release(void* inst, uint8_t button) {
BleHidInstance* ble_hid = inst;
furi_assert(ble_hid);
return ble_profile_hid_mouse_release(ble_hid->profile, button);
}
bool hid_ble_mouse_scroll(void* inst, int8_t delta) {
BleHidInstance* ble_hid = inst;
furi_assert(ble_hid);
return ble_profile_hid_mouse_scroll(ble_hid->profile, delta);
}
bool hid_ble_mouse_move(void* inst, int8_t dx, int8_t dy) {
BleHidInstance* ble_hid = inst;
furi_assert(ble_hid);
return ble_profile_hid_mouse_move(ble_hid->profile, dx, dy);
}

bool hid_ble_consumer_press(void* inst, uint16_t button) {
BleHidInstance* ble_hid = inst;
furi_assert(ble_hid);
Expand All @@ -174,6 +225,7 @@ bool hid_ble_release_all(void* inst) {
furi_assert(ble_hid);
bool state = ble_profile_hid_kb_release_all(ble_hid->profile);
state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile);
state &= ble_profile_hid_mouse_release_all(ble_hid->profile);
return state;
}

Expand All @@ -191,6 +243,10 @@ static const BadUsbHidApi hid_api_ble = {

.kb_press = hid_ble_kb_press,
.kb_release = hid_ble_kb_release,
.mouse_press = hid_ble_mouse_press,
.mouse_release = hid_ble_mouse_release,
.mouse_scroll = hid_ble_mouse_scroll,
.mouse_move = hid_ble_mouse_move,
.consumer_press = hid_ble_consumer_press,
.consumer_release = hid_ble_consumer_release,
.release_all = hid_ble_release_all,
Expand Down
4 changes: 4 additions & 0 deletions applications/main/bad_usb/helpers/bad_usb_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ typedef struct {

bool (*kb_press)(void* inst, uint16_t button);
bool (*kb_release)(void* inst, uint16_t button);
bool (*mouse_press)(void* inst, uint8_t button);
bool (*mouse_release)(void* inst, uint8_t button);
bool (*mouse_scroll)(void* inst, int8_t delta);
bool (*mouse_move)(void* inst, int8_t dx, int8_t dy);
bool (*consumer_press)(void* inst, uint16_t button);
bool (*consumer_release)(void* inst, uint16_t button);
bool (*release_all)(void* inst);
Expand Down
10 changes: 9 additions & 1 deletion applications/main/bad_usb/helpers/ducky_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,16 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
return cmd_result;
}

// Mouse Keys
uint16_t key = ducky_get_mouse_keycode_by_name(line_tmp);
if (key != HID_MOUSE_INVALID) {
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
return 0;
}

// Special keys + modifiers
uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false);
key = ducky_get_keycode(bad_usb, line_tmp, false);
if(key == HID_KEYBOARD_NONE) {
return ducky_error(bad_usb, "No keycode defined for %s", line_tmp);
}
Expand Down
74 changes: 74 additions & 0 deletions applications/main/bad_usb/helpers/ducky_script_commands.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <furi_hal.h>
#include <lib/toolbox/strint.h>
#include "ducky_script.h"
#include "ducky_script_i.h"

Expand Down Expand Up @@ -124,32 +125,64 @@ static int32_t ducky_fnc_altstring(BadUsbScript* bad_usb, const char* line, int3

static int32_t ducky_fnc_hold(BadUsbScript* bad_usb, const char* line, int32_t param) {
UNUSED(param);
bool isMouse = false;

line = &line[ducky_get_command_len(line) + 1];

// Handle Keyboard keys here
uint16_t key = ducky_get_keycode(bad_usb, line, true);
if(key == HID_KEYBOARD_NONE) {
return ducky_error(bad_usb, "No keycode defined for %s", line);
}

// Handle Mouse Keys here
key = ducky_get_mouse_keycode_by_name(line);
if (key != HID_MOUSE_INVALID) {
isMouse = true;
}

bad_usb->key_hold_nb++;
if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
return ducky_error(bad_usb, "Too many keys are hold");
}

if (isMouse) {
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
return 0;
}

bad_usb->hid->kb_press(bad_usb->hid_inst, key);
return 0;
}

static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_t param) {
UNUSED(param);
bool isMouse = false;

line = &line[ducky_get_command_len(line) + 1];

//Handle Keyboard Keys here
uint16_t key = ducky_get_keycode(bad_usb, line, true);
if(key == HID_KEYBOARD_NONE) {
return ducky_error(bad_usb, "No keycode defined for %s", line);
}

// Handle Mouse Keys here
key = ducky_get_mouse_keycode_by_name(line);
if (key != HID_MOUSE_INVALID) {
isMouse = true;
}

if(bad_usb->key_hold_nb == 0) {
return ducky_error(bad_usb, "No keys are hold");
}
bad_usb->key_hold_nb--;

if (isMouse) {
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
return 0;
}

bad_usb->hid->kb_release(bad_usb->hid_inst, key);
return 0;
}
Expand Down Expand Up @@ -191,6 +224,43 @@ static int32_t ducky_fnc_waitforbutton(BadUsbScript* bad_usb, const char* line,
return SCRIPT_STATE_WAIT_FOR_BTN;
}

static int32_t ducky_fnc_mouse_scroll(BadUsbScript* bad_usb, const char* line, int32_t param) {
UNUSED(param);

line = &line[strcspn(line, " ") + 1];
int32_t mouse_scroll_dist = 0;

if (strint_to_int32(line, NULL, &mouse_scroll_dist, 10) != StrintParseNoError) {
return ducky_error(bad_usb, "Invalid Number %s", line);
}

bad_usb->hid->mouse_scroll(bad_usb->hid_inst, mouse_scroll_dist);

return 0;
}

static int32_t ducky_fnc_mouse_move(BadUsbScript* bad_usb, const char* line, int32_t param) {
UNUSED(param);

line = &line[strcspn(line, " ") + 1];
int32_t mouse_move_x = 0;
int32_t mouse_move_y = 0;

if (strint_to_int32(line, NULL, &mouse_move_x, 10) != StrintParseNoError) {
return ducky_error(bad_usb, "Invalid Number %s", line);
}

line = &line[strcspn(line, " ") + 1];

if (strint_to_int32(line, NULL, &mouse_move_y, 10) != StrintParseNoError) {
return ducky_error(bad_usb, "Invalid Number %s", line);
}

bad_usb->hid->mouse_move(bad_usb->hid_inst, mouse_move_x, mouse_move_y);

return 0;
}

static const DuckyCmd ducky_commands[] = {
{"REM", NULL, -1},
{"ID", NULL, -1},
Expand All @@ -213,6 +283,10 @@ static const DuckyCmd ducky_commands[] = {
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
{"MEDIA", ducky_fnc_media, -1},
{"GLOBE", ducky_fnc_globe, -1},
{"MOUSEMOVE", ducky_fnc_mouse_move, -1},
{"MOUSE_MOVE", ducky_fnc_mouse_move, -1},
{"MOUSESCROLL", ducky_fnc_mouse_scroll, -1},
{"MOUSE_SCROLL", ducky_fnc_mouse_scroll, -1},
};

#define TAG "BadUsb"
Expand Down
4 changes: 4 additions & 0 deletions applications/main/bad_usb/helpers/ducky_script_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern "C" {

#define FILE_BUFFER_LEN 16

#define HID_MOUSE_INVALID 0

struct BadUsbScript {
FuriHalUsbHidConfig hid_cfg;
const BadUsbHidApi* hid;
Expand Down Expand Up @@ -55,6 +57,8 @@ uint16_t ducky_get_keycode_by_name(const char* param);

uint16_t ducky_get_media_keycode_by_name(const char* param);

uint8_t ducky_get_mouse_keycode_by_name(const char* param);

bool ducky_get_number(const char* param, uint32_t* val);

void ducky_numlock_on(BadUsbScript* bad_usb);
Expand Down
22 changes: 22 additions & 0 deletions applications/main/bad_usb/helpers/ducky_script_keycodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ static const DuckyKey ducky_media_keys[] = {
{"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT},
};

static const DuckyKey ducky_mouse_keys[] = {
{"LEFTCLICK", HID_MOUSE_BTN_LEFT},
{"LEFT_CLICK", HID_MOUSE_BTN_LEFT},
{"RIGHTCLICK", HID_MOUSE_BTN_RIGHT},
{"RIGHT_CLICK", HID_MOUSE_BTN_RIGHT},
{"MIDDLECLICK", HID_MOUSE_BTN_WHEEL},
{"MIDDLE_CLICK", HID_MOUSE_BTN_WHEEL},
{"WHEELCLICK", HID_MOUSE_BTN_WHEEL},
{"WHEEL_CLICK", HID_MOUSE_BTN_WHEEL},
};

uint16_t ducky_get_keycode_by_name(const char* param) {
for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) {
size_t key_cmd_len = strlen(ducky_keys[i].name);
Expand All @@ -131,3 +142,14 @@ uint16_t ducky_get_media_keycode_by_name(const char* param) {

return HID_CONSUMER_UNASSIGNED;
}

uint8_t ducky_get_mouse_keycode_by_name(const char* param) {
for (size_t i = 0; i < COUNT_OF(ducky_mouse_keys); i++) {
size_t key_cmd_len = strlen(ducky_mouse_keys[i].name);
if((strncmp(param, ducky_mouse_keys[i].name, key_cmd_len) == 0) && (ducky_is_line_end(param[key_cmd_len]))) {
return ducky_mouse_keys[i].keycode;
}
}

return HID_MOUSE_INVALID;
}
15 changes: 15 additions & 0 deletions documentation/file_formats/BadUsbScriptFormat.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,18 @@ Example:
`ID 1234:abcd Flipper Devices:Flipper Zero`

VID and PID are hex codes and are mandatory. Manufacturer and Product are text strings and are optional.

## Mouse Commands

Mouse movement and click commands. Mouse click commands support HOLD functionality.

| Command | Parameters | Notes |
| ------------- | -------------------------------| -------------------------------- |
| LEFTCLICK | None | |
| LEFT_CLICK | None | functionally same as LEFTCLICK |
| RIGHTCLICK | None | |
| RIGHT_CLICK | None | functionally same as RIGHTCLICK |
| MOUSEMOVE | x y: int move mount/direction | |
| MOUSE_MOVE | x y: int move mount/direction | functionally same as MOUSEMOVE |
| MOUSESCROLL | delta: int scroll distance | |
| MOUSE_SCROLL | delta: int scroll distance | functionally same as MOUSESCROLL |