ducky_script_commands.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include "../bad_kb_app_i.h"
  2. #include <furi_hal.h>
  3. #include <furi_hal_usb_hid.h>
  4. #include "ble_hid.h"
  5. #include "ducky_script.h"
  6. #include "ducky_script_i.h"
  7. typedef int32_t (*DuckyCmdCallback)(BadKbScript* bad_kb, const char* line, int32_t param);
  8. typedef struct {
  9. char* name;
  10. DuckyCmdCallback callback;
  11. int32_t param;
  12. } DuckyCmd;
  13. static int32_t ducky_fnc_delay(BadKbScript* bad_kb, const char* line, int32_t param) {
  14. UNUSED(param);
  15. line = &line[ducky_get_command_len(line) + 1];
  16. uint32_t delay_val = 0;
  17. bool state = ducky_get_number(line, &delay_val);
  18. if((state) && (delay_val > 0)) {
  19. return (int32_t)delay_val;
  20. }
  21. return ducky_error(bad_kb, "Invalid number %s", line);
  22. }
  23. static int32_t ducky_fnc_defdelay(BadKbScript* bad_kb, const char* line, int32_t param) {
  24. UNUSED(param);
  25. line = &line[ducky_get_command_len(line) + 1];
  26. bool state = ducky_get_number(line, &bad_kb->defdelay);
  27. if(!state) {
  28. return ducky_error(bad_kb, "Invalid number %s", line);
  29. }
  30. return 0;
  31. }
  32. static int32_t ducky_fnc_strdelay(BadKbScript* bad_kb, const char* line, int32_t param) {
  33. UNUSED(param);
  34. line = &line[ducky_get_command_len(line) + 1];
  35. bool state = ducky_get_number(line, &bad_kb->stringdelay);
  36. if(!state) {
  37. return ducky_error(bad_kb, "Invalid number %s", line);
  38. }
  39. return 0;
  40. }
  41. static int32_t ducky_fnc_string(BadKbScript* bad_kb, const char* line, int32_t param) {
  42. line = &line[ducky_get_command_len(line) + 1];
  43. furi_string_set_str(bad_kb->string_print, line);
  44. if(param == 1) {
  45. furi_string_cat(bad_kb->string_print, "\n");
  46. }
  47. if(bad_kb->stringdelay == 0) { // stringdelay not set - run command immediately
  48. bool state = ducky_string(bad_kb, furi_string_get_cstr(bad_kb->string_print));
  49. if(!state) {
  50. return ducky_error(bad_kb, "Invalid string %s", line);
  51. }
  52. } else { // stringdelay is set - run command in thread to keep handling external events
  53. return SCRIPT_STATE_STRING_START;
  54. }
  55. return 0;
  56. }
  57. static int32_t ducky_fnc_repeat(BadKbScript* bad_kb, const char* line, int32_t param) {
  58. UNUSED(param);
  59. line = &line[ducky_get_command_len(line) + 1];
  60. bool state = ducky_get_number(line, &bad_kb->repeat_cnt);
  61. if((!state) || (bad_kb->repeat_cnt == 0)) {
  62. return ducky_error(bad_kb, "Invalid number %s", line);
  63. }
  64. return 0;
  65. }
  66. static int32_t ducky_fnc_sysrq(BadKbScript* bad_kb, const char* line, int32_t param) {
  67. UNUSED(param);
  68. line = &line[ducky_get_command_len(line) + 1];
  69. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  70. if(bad_kb->bt) {
  71. ble_profile_hid_kb_press(
  72. bad_kb->app->ble_hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
  73. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  74. furi_delay_ms(bt_timeout);
  75. ble_profile_hid_kb_release_all(bad_kb->app->ble_hid);
  76. } else {
  77. furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
  78. furi_hal_hid_kb_press(key);
  79. furi_hal_hid_kb_release_all();
  80. }
  81. return 0;
  82. }
  83. static int32_t ducky_fnc_altchar(BadKbScript* bad_kb, const char* line, int32_t param) {
  84. UNUSED(param);
  85. line = &line[ducky_get_command_len(line) + 1];
  86. ducky_numlock_on(bad_kb);
  87. bool state = ducky_altchar(bad_kb, line);
  88. if(!state) {
  89. return ducky_error(bad_kb, "Invalid altchar %s", line);
  90. }
  91. return 0;
  92. }
  93. static int32_t ducky_fnc_altstring(BadKbScript* bad_kb, const char* line, int32_t param) {
  94. UNUSED(param);
  95. line = &line[ducky_get_command_len(line) + 1];
  96. ducky_numlock_on(bad_kb);
  97. bool state = ducky_altstring(bad_kb, line);
  98. if(!state) {
  99. return ducky_error(bad_kb, "Invalid altstring %s", line);
  100. }
  101. return 0;
  102. }
  103. static int32_t ducky_fnc_hold(BadKbScript* bad_kb, const char* line, int32_t param) {
  104. UNUSED(param);
  105. line = &line[ducky_get_command_len(line) + 1];
  106. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  107. if(key == HID_KEYBOARD_NONE) {
  108. return ducky_error(bad_kb, "No keycode defined for %s", line);
  109. }
  110. bad_kb->key_hold_nb++;
  111. if(bad_kb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
  112. return ducky_error(bad_kb, "Too many keys are hold");
  113. }
  114. if(bad_kb->bt) {
  115. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  116. } else {
  117. furi_hal_hid_kb_press(key);
  118. }
  119. return 0;
  120. }
  121. static int32_t ducky_fnc_release(BadKbScript* bad_kb, const char* line, int32_t param) {
  122. UNUSED(param);
  123. line = &line[ducky_get_command_len(line) + 1];
  124. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  125. if(key == HID_KEYBOARD_NONE) {
  126. return ducky_error(bad_kb, "No keycode defined for %s", line);
  127. }
  128. if(bad_kb->key_hold_nb == 0) {
  129. return ducky_error(bad_kb, "No keys are hold");
  130. }
  131. bad_kb->key_hold_nb--;
  132. if(bad_kb->bt) {
  133. ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
  134. } else {
  135. furi_hal_hid_kb_release(key);
  136. }
  137. return 0;
  138. }
  139. static int32_t ducky_fnc_waitforbutton(BadKbScript* bad_kb, const char* line, int32_t param) {
  140. UNUSED(param);
  141. UNUSED(bad_kb);
  142. UNUSED(line);
  143. return SCRIPT_STATE_WAIT_FOR_BTN;
  144. }
  145. static const DuckyCmd ducky_commands[] = {
  146. {"REM", NULL, -1},
  147. {"ID", NULL, -1},
  148. {"BT_ID", NULL, -1},
  149. {"DELAY", ducky_fnc_delay, -1},
  150. {"STRING", ducky_fnc_string, 0},
  151. {"STRINGLN", ducky_fnc_string, 1},
  152. {"DEFAULT_DELAY", ducky_fnc_defdelay, -1},
  153. {"DEFAULTDELAY", ducky_fnc_defdelay, -1},
  154. {"STRINGDELAY", ducky_fnc_strdelay, -1},
  155. {"STRING_DELAY", ducky_fnc_strdelay, -1},
  156. {"REPEAT", ducky_fnc_repeat, -1},
  157. {"SYSRQ", ducky_fnc_sysrq, -1},
  158. {"ALTCHAR", ducky_fnc_altchar, -1},
  159. {"ALTSTRING", ducky_fnc_altstring, -1},
  160. {"ALTCODE", ducky_fnc_altstring, -1},
  161. {"HOLD", ducky_fnc_hold, -1},
  162. {"RELEASE", ducky_fnc_release, -1},
  163. {"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
  164. };
  165. #define TAG "BadKb"
  166. #define WORKER_TAG TAG "Worker"
  167. int32_t ducky_execute_cmd(BadKbScript* bad_kb, const char* line) {
  168. size_t cmd_word_len = strcspn(line, " ");
  169. for(size_t i = 0; i < COUNT_OF(ducky_commands); i++) {
  170. size_t cmd_compare_len = strlen(ducky_commands[i].name);
  171. if(cmd_compare_len != cmd_word_len) {
  172. continue;
  173. }
  174. if(strncmp(line, ducky_commands[i].name, cmd_compare_len) == 0) {
  175. if(ducky_commands[i].callback == NULL) {
  176. return 0;
  177. } else {
  178. return ((ducky_commands[i].callback)(bad_kb, line, ducky_commands[i].param));
  179. }
  180. }
  181. }
  182. return SCRIPT_STATE_CMD_UNKNOWN;
  183. }