Browse Source

[#1989] updated parser and added stringln, hold and release (#2448)

* 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>
Leo Smith 2 years ago
parent
commit
5b05aeea82

+ 59 - 220
applications/main/bad_usb/bad_usb_script.c

@@ -6,11 +6,11 @@
 #include <furi_hal_usb_hid.h>
 #include <storage/storage.h>
 #include "bad_usb_script.h"
+#include "mnemonic.h"
 #include <dolphin/dolphin.h>
 
 #define TAG "BadUSB"
 #define WORKER_TAG TAG "Worker"
-#define FILE_BUFFER_LEN 16
 
 #define SCRIPT_STATE_ERROR (-1)
 #define SCRIPT_STATE_END (-2)
@@ -26,24 +26,6 @@ typedef enum {
     WorkerEvtDisconnect = (1 << 3),
 } 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 {
     char* name;
     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_delay[] = {"DELAY "};
 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_2[] = {"DEFAULTDELAY "};
 static const char ducky_cmd_stringdelay_1[] = {"STRINGDELAY "};
 static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "};
 static const char ducky_cmd_repeat[] = {"REPEAT "};
 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_altstr_1[] = {"ALTSTRING "};
 static const char ducky_cmd_altstr_2[] = {"ALTCODE "};
 
-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 uint32_t ducky_get_command_len(const char* line) {
+uint32_t ducky_get_command_len(const char* line) {
     uint32_t len = strlen(line);
     for(uint32_t i = 0; i < len; i++) {
         if(line[i] == ' ') return i;
@@ -153,84 +116,11 @@ static uint32_t ducky_get_command_len(const char* line) {
     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'));
 }
 
-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;
-}
-
-static uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) {
+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++) {
         size_t key_cmd_len = strlen(ducky_keys[i].name);
         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) {
     uint32_t line_len = furi_string_size(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) {
         return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
     }
-
     FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp);
-
-    // General commands
-    if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) {
-        // REM - comment line
-        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;
-        }
+    // Ducky Lang Functions
+    for(size_t i = 0; ducky_cmd_table[i]; i++) {
+        if(strncmp(line_tmp, ducky_cmd_table[i], strlen(ducky_cmd_table[i])) == 0)
+            return ((fnc_ptr[i])(bad_usb, line, line_tmp, error, error_len));
+    }
+    // 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, "Invalid number %s", line_tmp);
+            snprintf(error, error_len, "No keycode defined for %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
+    }
+    if((key & 0xFF00) != 0) {
+        // It's a modifier key
         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);
+        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) {

+ 26 - 1
applications/main/bad_usb/bad_usb_script.h

@@ -5,8 +5,9 @@ extern "C" {
 #endif
 
 #include <furi.h>
+#include <furi_hal.h>
 
-typedef struct BadUsbScript BadUsbScript;
+#define FILE_BUFFER_LEN 16
 
 typedef enum {
     BadUsbStateInit,
@@ -29,6 +30,24 @@ typedef struct {
     char error[64];
 } 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);
 
 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);
 
+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
 }
 #endif

+ 327 - 0
applications/main/bad_usb/mnemonic.c

@@ -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 - 0
applications/main/bad_usb/mnemonic.h

@@ -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