* updated parser and added stringln, hold and release * removed unused code as requested from PR * BadUsb: tiny change to trigger rebuild Co-authored-by: p4p1 <p4p1@vivaldi.net> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									780da7d4d5
								
							
						
					
					
						commit
						5b05aeea82
					
				| @ -6,11 +6,11 @@ | |||||||
| #include <furi_hal_usb_hid.h> | #include <furi_hal_usb_hid.h> | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
| #include "bad_usb_script.h" | #include "bad_usb_script.h" | ||||||
|  | #include "mnemonic.h" | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "BadUSB" | #define TAG "BadUSB" | ||||||
| #define WORKER_TAG TAG "Worker" | #define WORKER_TAG TAG "Worker" | ||||||
| #define FILE_BUFFER_LEN 16 |  | ||||||
| 
 | 
 | ||||||
| #define SCRIPT_STATE_ERROR (-1) | #define SCRIPT_STATE_ERROR (-1) | ||||||
| #define SCRIPT_STATE_END (-2) | #define SCRIPT_STATE_END (-2) | ||||||
| @ -26,24 +26,6 @@ typedef enum { | |||||||
|     WorkerEvtDisconnect = (1 << 3), |     WorkerEvtDisconnect = (1 << 3), | ||||||
| } WorkerEvtFlags; | } WorkerEvtFlags; | ||||||
| 
 | 
 | ||||||
| struct BadUsbScript { |  | ||||||
|     FuriHalUsbHidConfig hid_cfg; |  | ||||||
|     BadUsbState st; |  | ||||||
|     FuriString* file_path; |  | ||||||
|     uint32_t defdelay; |  | ||||||
|     uint16_t layout[128]; |  | ||||||
|     uint32_t stringdelay; |  | ||||||
|     FuriThread* thread; |  | ||||||
|     uint8_t file_buf[FILE_BUFFER_LEN + 1]; |  | ||||||
|     uint8_t buf_start; |  | ||||||
|     uint8_t buf_len; |  | ||||||
|     bool file_end; |  | ||||||
|     FuriString* line; |  | ||||||
| 
 |  | ||||||
|     FuriString* line_prev; |  | ||||||
|     uint32_t repeat_cnt; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     char* name; |     char* name; | ||||||
|     uint16_t keycode; |     uint16_t keycode; | ||||||
| @ -112,40 +94,21 @@ static const char ducky_cmd_comment[] = {"REM"}; | |||||||
| static const char ducky_cmd_id[] = {"ID"}; | static const char ducky_cmd_id[] = {"ID"}; | ||||||
| static const char ducky_cmd_delay[] = {"DELAY "}; | static const char ducky_cmd_delay[] = {"DELAY "}; | ||||||
| static const char ducky_cmd_string[] = {"STRING "}; | static const char ducky_cmd_string[] = {"STRING "}; | ||||||
|  | static const char ducky_cmd_stringln[] = {"STRINGLN "}; | ||||||
| static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; | static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; | ||||||
| static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "}; | static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "}; | ||||||
| static const char ducky_cmd_stringdelay_1[] = {"STRINGDELAY "}; | static const char ducky_cmd_stringdelay_1[] = {"STRINGDELAY "}; | ||||||
| static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "}; | static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "}; | ||||||
| static const char ducky_cmd_repeat[] = {"REPEAT "}; | static const char ducky_cmd_repeat[] = {"REPEAT "}; | ||||||
| static const char ducky_cmd_sysrq[] = {"SYSRQ "}; | static const char ducky_cmd_sysrq[] = {"SYSRQ "}; | ||||||
|  | static const char ducky_cmd_hold[] = {"HOLD "}; | ||||||
|  | static const char ducky_cmd_release[] = {"RELEASE "}; | ||||||
| 
 | 
 | ||||||
| static const char ducky_cmd_altchar[] = {"ALTCHAR "}; | static const char ducky_cmd_altchar[] = {"ALTCHAR "}; | ||||||
| static const char ducky_cmd_altstr_1[] = {"ALTSTRING "}; | static const char ducky_cmd_altstr_1[] = {"ALTSTRING "}; | ||||||
| static const char ducky_cmd_altstr_2[] = {"ALTCODE "}; | static const char ducky_cmd_altstr_2[] = {"ALTCODE "}; | ||||||
| 
 | 
 | ||||||
| static const uint8_t numpad_keys[10] = { | uint32_t ducky_get_command_len(const char* line) { | ||||||
|     HID_KEYPAD_0, |  | ||||||
|     HID_KEYPAD_1, |  | ||||||
|     HID_KEYPAD_2, |  | ||||||
|     HID_KEYPAD_3, |  | ||||||
|     HID_KEYPAD_4, |  | ||||||
|     HID_KEYPAD_5, |  | ||||||
|     HID_KEYPAD_6, |  | ||||||
|     HID_KEYPAD_7, |  | ||||||
|     HID_KEYPAD_8, |  | ||||||
|     HID_KEYPAD_9, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static bool ducky_get_number(const char* param, uint32_t* val) { |  | ||||||
|     uint32_t value = 0; |  | ||||||
|     if(sscanf(param, "%lu", &value) == 1) { |  | ||||||
|         *val = value; |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static uint32_t ducky_get_command_len(const char* line) { |  | ||||||
|     uint32_t len = strlen(line); |     uint32_t len = strlen(line); | ||||||
|     for(uint32_t i = 0; i < len; i++) { |     for(uint32_t i = 0; i < len; i++) { | ||||||
|         if(line[i] == ' ') return i; |         if(line[i] == ' ') return i; | ||||||
| @ -153,84 +116,11 @@ static uint32_t ducky_get_command_len(const char* line) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool ducky_is_line_end(const char chr) { | bool ducky_is_line_end(const char chr) { | ||||||
|     return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n')); |     return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n')); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ducky_numlock_on() { | uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) { | ||||||
|     if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) { |  | ||||||
|         furi_hal_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK); |  | ||||||
|         furi_hal_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool ducky_numpad_press(const char num) { |  | ||||||
|     if((num < '0') || (num > '9')) return false; |  | ||||||
| 
 |  | ||||||
|     uint16_t key = numpad_keys[num - '0']; |  | ||||||
|     furi_hal_hid_kb_press(key); |  | ||||||
|     furi_hal_hid_kb_release(key); |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool ducky_altchar(const char* charcode) { |  | ||||||
|     uint8_t i = 0; |  | ||||||
|     bool state = false; |  | ||||||
| 
 |  | ||||||
|     FURI_LOG_I(WORKER_TAG, "char %s", charcode); |  | ||||||
| 
 |  | ||||||
|     furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT); |  | ||||||
| 
 |  | ||||||
|     while(!ducky_is_line_end(charcode[i])) { |  | ||||||
|         state = ducky_numpad_press(charcode[i]); |  | ||||||
|         if(state == false) break; |  | ||||||
|         i++; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     furi_hal_hid_kb_release(KEY_MOD_LEFT_ALT); |  | ||||||
|     return state; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool ducky_altstring(const char* param) { |  | ||||||
|     uint32_t i = 0; |  | ||||||
|     bool state = false; |  | ||||||
| 
 |  | ||||||
|     while(param[i] != '\0') { |  | ||||||
|         if((param[i] < ' ') || (param[i] > '~')) { |  | ||||||
|             i++; |  | ||||||
|             continue; // Skip non-printable chars
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         char temp_str[4]; |  | ||||||
|         snprintf(temp_str, 4, "%u", param[i]); |  | ||||||
| 
 |  | ||||||
|         state = ducky_altchar(temp_str); |  | ||||||
|         if(state == false) break; |  | ||||||
|         i++; |  | ||||||
|     } |  | ||||||
|     return state; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool ducky_string(BadUsbScript* bad_usb, const char* param) { |  | ||||||
|     uint32_t i = 0; |  | ||||||
| 
 |  | ||||||
|     while(param[i] != '\0') { |  | ||||||
|         uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]); |  | ||||||
|         if(keycode != HID_KEYBOARD_NONE) { |  | ||||||
|             furi_hal_hid_kb_press(keycode); |  | ||||||
|             furi_hal_hid_kb_release(keycode); |  | ||||||
|             if(bad_usb->stringdelay > 0) { |  | ||||||
|                 furi_delay_ms(bad_usb->stringdelay); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         i++; |  | ||||||
|     } |  | ||||||
|     bad_usb->stringdelay = 0; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) { |  | ||||||
|     for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { |     for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { | ||||||
|         size_t key_cmd_len = strlen(ducky_keys[i].name); |         size_t key_cmd_len = strlen(ducky_keys[i].name); | ||||||
|         if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && |         if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && | ||||||
| @ -248,119 +138,68 @@ static int32_t | |||||||
|     ducky_parse_line(BadUsbScript* bad_usb, FuriString* line, char* error, size_t error_len) { |     ducky_parse_line(BadUsbScript* bad_usb, FuriString* line, char* error, size_t error_len) { | ||||||
|     uint32_t line_len = furi_string_size(line); |     uint32_t line_len = furi_string_size(line); | ||||||
|     const char* line_tmp = furi_string_get_cstr(line); |     const char* line_tmp = furi_string_get_cstr(line); | ||||||
|     bool state = false; |     const char* ducky_cmd_table[] = { | ||||||
|  |         ducky_cmd_comment, | ||||||
|  |         ducky_cmd_id, | ||||||
|  |         ducky_cmd_delay, | ||||||
|  |         ducky_cmd_string, | ||||||
|  |         ducky_cmd_defdelay_1, | ||||||
|  |         ducky_cmd_defdelay_2, | ||||||
|  |         ducky_cmd_stringdelay_1, | ||||||
|  |         ducky_cmd_stringdelay_2, | ||||||
|  |         ducky_cmd_repeat, | ||||||
|  |         ducky_cmd_sysrq, | ||||||
|  |         ducky_cmd_altchar, | ||||||
|  |         ducky_cmd_altstr_1, | ||||||
|  |         ducky_cmd_altstr_2, | ||||||
|  |         ducky_cmd_stringln, | ||||||
|  |         ducky_cmd_hold, | ||||||
|  |         ducky_cmd_release, | ||||||
|  |         NULL}; | ||||||
|  |     int32_t (*fnc_ptr[])(BadUsbScript*, FuriString*, const char*, char*, size_t) = { | ||||||
|  |         &ducky_fnc_noop, | ||||||
|  |         &ducky_fnc_noop, | ||||||
|  |         &ducky_fnc_delay, | ||||||
|  |         &ducky_fnc_string, | ||||||
|  |         &ducky_fnc_defdelay, | ||||||
|  |         &ducky_fnc_defdelay, | ||||||
|  |         &ducky_fnc_strdelay, | ||||||
|  |         &ducky_fnc_strdelay, | ||||||
|  |         &ducky_fnc_repeat, | ||||||
|  |         &ducky_fnc_sysrq, | ||||||
|  |         &ducky_fnc_altchar, | ||||||
|  |         &ducky_fnc_altstring, | ||||||
|  |         &ducky_fnc_altstring, | ||||||
|  |         &ducky_fnc_stringln, | ||||||
|  |         &ducky_fnc_hold, | ||||||
|  |         &ducky_fnc_release, | ||||||
|  |         NULL}; | ||||||
| 
 | 
 | ||||||
|     if(line_len == 0) { |     if(line_len == 0) { | ||||||
|         return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
 |         return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
 | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp); |     FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp); | ||||||
| 
 |     // Ducky Lang Functions
 | ||||||
|     // General commands
 |     for(size_t i = 0; ducky_cmd_table[i]; i++) { | ||||||
|     if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) { |         if(strncmp(line_tmp, ducky_cmd_table[i], strlen(ducky_cmd_table[i])) == 0) | ||||||
|         // REM - comment line
 |             return ((fnc_ptr[i])(bad_usb, line, line_tmp, error, error_len)); | ||||||
|         return (0); |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { |  | ||||||
|         // ID - executed in ducky_script_preload
 |  | ||||||
|         return (0); |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) { |  | ||||||
|         // DELAY
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         uint32_t delay_val = 0; |  | ||||||
|         state = ducky_get_number(line_tmp, &delay_val); |  | ||||||
|         if((state) && (delay_val > 0)) { |  | ||||||
|             return (int32_t)delay_val; |  | ||||||
|         } |  | ||||||
|         if(error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid number %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return SCRIPT_STATE_ERROR; |  | ||||||
|     } else if( |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_defdelay_1, strlen(ducky_cmd_defdelay_1)) == 0) || |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_defdelay_2, strlen(ducky_cmd_defdelay_2)) == 0)) { |  | ||||||
|         // DEFAULT_DELAY
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         state = ducky_get_number(line_tmp, &bad_usb->defdelay); |  | ||||||
|         if(!state && error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid number %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |  | ||||||
|     } else if( |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_stringdelay_1, strlen(ducky_cmd_stringdelay_1)) == 0) || |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_stringdelay_2, strlen(ducky_cmd_stringdelay_2)) == 0)) { |  | ||||||
|         //STRINGDELAY, finally it's here
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         state = ducky_get_number(line_tmp, &bad_usb->stringdelay); |  | ||||||
|         if((state) && (bad_usb->stringdelay > 0)) { |  | ||||||
|             return state; |  | ||||||
|         } |  | ||||||
|         if(error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid number %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return SCRIPT_STATE_ERROR; |  | ||||||
| 
 |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { |  | ||||||
|         // STRING
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         state = ducky_string(bad_usb, line_tmp); |  | ||||||
|         if(!state && error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid string %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) { |  | ||||||
|         // ALTCHAR
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         ducky_numlock_on(); |  | ||||||
|         state = ducky_altchar(line_tmp); |  | ||||||
|         if(!state && error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid altchar %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |  | ||||||
|     } else if( |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_altstr_1, strlen(ducky_cmd_altstr_1)) == 0) || |  | ||||||
|         (strncmp(line_tmp, ducky_cmd_altstr_2, strlen(ducky_cmd_altstr_2)) == 0)) { |  | ||||||
|         // ALTSTRING
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         ducky_numlock_on(); |  | ||||||
|         state = ducky_altstring(line_tmp); |  | ||||||
|         if(!state && error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid altstring %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) { |  | ||||||
|         // REPEAT
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt); |  | ||||||
|         if(!state && error != NULL) { |  | ||||||
|             snprintf(error, error_len, "Invalid number %s", line_tmp); |  | ||||||
|         } |  | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |  | ||||||
|     } else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) { |  | ||||||
|         // SYSRQ
 |  | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|         uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); |  | ||||||
|         furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); |  | ||||||
|         furi_hal_hid_kb_press(key); |  | ||||||
|         furi_hal_hid_kb_release_all(); |  | ||||||
|         return (0); |  | ||||||
|     } else { |  | ||||||
|         // Special keys + modifiers
 |  | ||||||
|         uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false); |  | ||||||
|         if(key == HID_KEYBOARD_NONE) { |  | ||||||
|             if(error != NULL) { |  | ||||||
|                 snprintf(error, error_len, "No keycode defined for %s", line_tmp); |  | ||||||
|             } |  | ||||||
|             return SCRIPT_STATE_ERROR; |  | ||||||
|         } |  | ||||||
|         if((key & 0xFF00) != 0) { |  | ||||||
|             // It's a modifier key
 |  | ||||||
|             line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |  | ||||||
|             key |= ducky_get_keycode(bad_usb, line_tmp, true); |  | ||||||
|         } |  | ||||||
|         furi_hal_hid_kb_press(key); |  | ||||||
|         furi_hal_hid_kb_release(key); |  | ||||||
|         return (0); |  | ||||||
|     } |     } | ||||||
|  |     // Special keys + modifiers
 | ||||||
|  |     uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false); | ||||||
|  |     if(key == HID_KEYBOARD_NONE) { | ||||||
|  |         if(error != NULL) { | ||||||
|  |             snprintf(error, error_len, "No keycode defined for %s", line_tmp); | ||||||
|  |         } | ||||||
|  |         return SCRIPT_STATE_ERROR; | ||||||
|  |     } | ||||||
|  |     if((key & 0xFF00) != 0) { | ||||||
|  |         // It's a modifier key
 | ||||||
|  |         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |         key |= ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|  |     } | ||||||
|  |     furi_hal_hid_kb_press(key); | ||||||
|  |     furi_hal_hid_kb_release(key); | ||||||
|  |     return (0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) { | static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) { | ||||||
|  | |||||||
| @ -5,8 +5,9 @@ extern "C" { | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
|  | #include <furi_hal.h> | ||||||
| 
 | 
 | ||||||
| typedef struct BadUsbScript BadUsbScript; | #define FILE_BUFFER_LEN 16 | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     BadUsbStateInit, |     BadUsbStateInit, | ||||||
| @ -29,6 +30,24 @@ typedef struct { | |||||||
|     char error[64]; |     char error[64]; | ||||||
| } BadUsbState; | } BadUsbState; | ||||||
| 
 | 
 | ||||||
|  | typedef struct BadUsbScript { | ||||||
|  |     FuriHalUsbHidConfig hid_cfg; | ||||||
|  |     BadUsbState st; | ||||||
|  |     FuriString* file_path; | ||||||
|  |     uint32_t defdelay; | ||||||
|  |     uint16_t layout[128]; | ||||||
|  |     uint32_t stringdelay; | ||||||
|  |     FuriThread* thread; | ||||||
|  |     uint8_t file_buf[FILE_BUFFER_LEN + 1]; | ||||||
|  |     uint8_t buf_start; | ||||||
|  |     uint8_t buf_len; | ||||||
|  |     bool file_end; | ||||||
|  |     FuriString* line; | ||||||
|  | 
 | ||||||
|  |     FuriString* line_prev; | ||||||
|  |     uint32_t repeat_cnt; | ||||||
|  | } BadUsbScript; | ||||||
|  | 
 | ||||||
| BadUsbScript* bad_usb_script_open(FuriString* file_path); | BadUsbScript* bad_usb_script_open(FuriString* file_path); | ||||||
| 
 | 
 | ||||||
| void bad_usb_script_close(BadUsbScript* bad_usb); | void bad_usb_script_close(BadUsbScript* bad_usb); | ||||||
| @ -43,6 +62,12 @@ void bad_usb_script_toggle(BadUsbScript* bad_usb); | |||||||
| 
 | 
 | ||||||
| BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb); | BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb); | ||||||
| 
 | 
 | ||||||
|  | uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars); | ||||||
|  | 
 | ||||||
|  | uint32_t ducky_get_command_len(const char* line); | ||||||
|  | 
 | ||||||
|  | bool ducky_is_line_end(const char chr); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
							
								
								
									
										327
									
								
								applications/main/bad_usb/mnemonic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								applications/main/bad_usb/mnemonic.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,327 @@ | |||||||
|  | #include <furi_hal.h> | ||||||
|  | #include <furi_hal_usb_hid.h> | ||||||
|  | #include "mnemonic.h" | ||||||
|  | 
 | ||||||
|  | #define TAG "BadUSB" | ||||||
|  | #define WORKER_TAG TAG "Worker" | ||||||
|  | 
 | ||||||
|  | #define FILE_BUFFER_LEN 16 | ||||||
|  | #define SCRIPT_STATE_ERROR (-1) | ||||||
|  | #define SCRIPT_STATE_END (-2) | ||||||
|  | #define SCRIPT_STATE_NEXT_LINE (-3) | ||||||
|  | 
 | ||||||
|  | #define BADUSB_ASCII_TO_KEY(script, x) \ | ||||||
|  |     (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) | ||||||
|  | 
 | ||||||
|  | static const uint8_t numpad_keys[10] = { | ||||||
|  |     HID_KEYPAD_0, | ||||||
|  |     HID_KEYPAD_1, | ||||||
|  |     HID_KEYPAD_2, | ||||||
|  |     HID_KEYPAD_3, | ||||||
|  |     HID_KEYPAD_4, | ||||||
|  |     HID_KEYPAD_5, | ||||||
|  |     HID_KEYPAD_6, | ||||||
|  |     HID_KEYPAD_7, | ||||||
|  |     HID_KEYPAD_8, | ||||||
|  |     HID_KEYPAD_9, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static bool ducky_get_number(const char* param, uint32_t* val) { | ||||||
|  |     uint32_t value = 0; | ||||||
|  |     if(sscanf(param, "%lu", &value) == 1) { | ||||||
|  |         *val = value; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void ducky_numlock_on() { | ||||||
|  |     if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) { | ||||||
|  |         furi_hal_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK); | ||||||
|  |         furi_hal_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | static bool ducky_numpad_press(const char num) { | ||||||
|  |     if((num < '0') || (num > '9')) return false; | ||||||
|  | 
 | ||||||
|  |     uint16_t key = numpad_keys[num - '0']; | ||||||
|  |     furi_hal_hid_kb_press(key); | ||||||
|  |     furi_hal_hid_kb_release(key); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool ducky_altchar(const char* charcode) { | ||||||
|  |     uint8_t i = 0; | ||||||
|  |     bool state = false; | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(WORKER_TAG, "char %s", charcode); | ||||||
|  | 
 | ||||||
|  |     furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT); | ||||||
|  | 
 | ||||||
|  |     while(!ducky_is_line_end(charcode[i])) { | ||||||
|  |         state = ducky_numpad_press(charcode[i]); | ||||||
|  |         if(state == false) break; | ||||||
|  |         i++; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_hid_kb_release(KEY_MOD_LEFT_ALT); | ||||||
|  |     return state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool ducky_altstring(const char* param) { | ||||||
|  |     uint32_t i = 0; | ||||||
|  |     bool state = false; | ||||||
|  | 
 | ||||||
|  |     while(param[i] != '\0') { | ||||||
|  |         if((param[i] < ' ') || (param[i] > '~')) { | ||||||
|  |             i++; | ||||||
|  |             continue; // Skip non-printable chars
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         char temp_str[4]; | ||||||
|  |         snprintf(temp_str, 4, "%u", param[i]); | ||||||
|  | 
 | ||||||
|  |         state = ducky_altchar(temp_str); | ||||||
|  |         if(state == false) break; | ||||||
|  |         i++; | ||||||
|  |     } | ||||||
|  |     return state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool ducky_string(BadUsbScript* bad_usb, const char* param) { | ||||||
|  |     uint32_t i = 0; | ||||||
|  | 
 | ||||||
|  |     while(param[i] != '\0') { | ||||||
|  |         uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]); | ||||||
|  |         if(keycode != HID_KEYBOARD_NONE) { | ||||||
|  |             furi_hal_hid_kb_press(keycode); | ||||||
|  |             furi_hal_hid_kb_release(keycode); | ||||||
|  |             if(bad_usb->stringdelay > 0) { | ||||||
|  |                 furi_delay_ms(bad_usb->stringdelay); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         i++; | ||||||
|  |     } | ||||||
|  |     bad_usb->stringdelay = 0; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_noop( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     (void)bad_usb; | ||||||
|  |     (void)line; | ||||||
|  |     (void)line_tmp; | ||||||
|  |     (void)error; | ||||||
|  |     (void)error_len; | ||||||
|  |     return (0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_delay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)bad_usb; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     uint32_t delay_val = 0; | ||||||
|  |     state = ducky_get_number(line_tmp, &delay_val); | ||||||
|  |     if((state) && (delay_val > 0)) { | ||||||
|  |         return (int32_t)delay_val; | ||||||
|  |     } | ||||||
|  |     if(error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid number %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_defdelay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     state = ducky_get_number(line_tmp, &bad_usb->defdelay); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid number %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_strdelay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     state = ducky_get_number(line_tmp, &bad_usb->stringdelay); | ||||||
|  |     if((state) && (bad_usb->stringdelay > 0)) { | ||||||
|  |         return state; | ||||||
|  |     } | ||||||
|  |     if(error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid number %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_string( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     state = ducky_string(bad_usb, line_tmp); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid string %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_repeat( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     state = ducky_get_number(line_tmp, &bad_usb->repeat_cnt); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid number %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_sysrq( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     (void)error; | ||||||
|  |     (void)error_len; | ||||||
|  |     (void)line; | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|  |     furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); | ||||||
|  |     furi_hal_hid_kb_press(key); | ||||||
|  |     furi_hal_hid_kb_release_all(); | ||||||
|  |     return (0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_altchar( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)bad_usb; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     ducky_numlock_on(); | ||||||
|  |     state = ducky_altchar(line_tmp); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid altchar %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_altstring( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)bad_usb; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     ducky_numlock_on(); | ||||||
|  |     state = ducky_altstring(line_tmp); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid altstring %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_stringln( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     bool state = false; | ||||||
|  |     (void)line; | ||||||
|  | 
 | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     state = ducky_string(bad_usb, line_tmp); | ||||||
|  |     if(!state && error != NULL) { | ||||||
|  |         snprintf(error, error_len, "Invalid string %s", line_tmp); | ||||||
|  |     } | ||||||
|  |     furi_hal_hid_kb_press(HID_KEYBOARD_RETURN); | ||||||
|  |     furi_hal_hid_kb_release(HID_KEYBOARD_RETURN); | ||||||
|  |     return (state) ? (0) : SCRIPT_STATE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_hold( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     (void)line; | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|  |     if(key == HID_KEYBOARD_NONE) { | ||||||
|  |         if(error != NULL) { | ||||||
|  |             snprintf(error, error_len, "No keycode defined for %s", line_tmp); | ||||||
|  |         } | ||||||
|  |         return SCRIPT_STATE_ERROR; | ||||||
|  |     } | ||||||
|  |     furi_hal_hid_kb_press(key); | ||||||
|  |     return (0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ducky_fnc_release( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len) { | ||||||
|  |     (void)line; | ||||||
|  |     line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|  |     uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|  |     if(key == HID_KEYBOARD_NONE) { | ||||||
|  |         if(error != NULL) { | ||||||
|  |             snprintf(error, error_len, "No keycode defined for %s", line_tmp); | ||||||
|  |         } | ||||||
|  |         return SCRIPT_STATE_ERROR; | ||||||
|  |     } | ||||||
|  |     furi_hal_hid_kb_release(key); | ||||||
|  |     return (0); | ||||||
|  | } | ||||||
							
								
								
									
										96
									
								
								applications/main/bad_usb/mnemonic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								applications/main/bad_usb/mnemonic.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include "bad_usb_script.h" | ||||||
|  | 
 | ||||||
|  | // A no opperation function
 | ||||||
|  | int32_t ducky_fnc_noop( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // DELAY
 | ||||||
|  | int32_t ducky_fnc_delay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // DEFAULTDELAY
 | ||||||
|  | int32_t ducky_fnc_defdelay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // STRINGDELAY
 | ||||||
|  | int32_t ducky_fnc_strdelay( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // STRING
 | ||||||
|  | int32_t ducky_fnc_string( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // STRINGLN
 | ||||||
|  | int32_t ducky_fnc_stringln( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // REPEAT
 | ||||||
|  | int32_t ducky_fnc_repeat( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // SYSRQ
 | ||||||
|  | int32_t ducky_fnc_sysrq( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // ALTCHAR
 | ||||||
|  | int32_t ducky_fnc_altchar( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // ALTSTRING
 | ||||||
|  | int32_t ducky_fnc_altstring( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // HOLD
 | ||||||
|  | int32_t ducky_fnc_hold( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | // RELEASE
 | ||||||
|  | int32_t ducky_fnc_release( | ||||||
|  |     BadUsbScript* bad_usb, | ||||||
|  |     FuriString* line, | ||||||
|  |     const char* line_tmp, | ||||||
|  |     char* error, | ||||||
|  |     size_t error_len); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Leo Smith
						Leo Smith