attack.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. #include "attack.h"
  2. #include "../fuzzer_i.h"
  3. #include <input/input.h>
  4. #include <gui/elements.h>
  5. #define ATTACK_SCENE_MAX_UID_LENGTH 25
  6. #define UID_MAX_DISPLAYED_LEN (8U)
  7. #define LEFT_RIGHT_OFFSET (3U)
  8. #define LINE_1_Y (12U)
  9. #define LINE_2_Y (24U)
  10. #define LINE_3_Y (36U)
  11. #define LINE_4_Y (48U)
  12. struct FuzzerViewAttack {
  13. View* view;
  14. FuzzerViewAttackCallback callback;
  15. void* context;
  16. };
  17. typedef struct {
  18. uint8_t time_delay; // 1 = 100ms
  19. uint8_t time_delay_min; // 1 = 100ms
  20. uint8_t emu_time; // 1 = 100ms
  21. uint8_t emu_time_min; // 1 = 100ms
  22. bool td_emt_cursor; // false - time_delay, true - emu_time
  23. const char* attack_name;
  24. const char* protocol_name;
  25. FuzzerAttackState attack_state;
  26. FuriString* uid_str;
  27. } FuzzerViewAttackModel;
  28. void fuzzer_view_attack_reset_data(
  29. FuzzerViewAttack* view,
  30. const char* attack_name,
  31. const char* protocol_name) {
  32. furi_assert(view);
  33. with_view_model(
  34. view->view,
  35. FuzzerViewAttackModel * model,
  36. {
  37. model->attack_name = attack_name;
  38. model->protocol_name = protocol_name;
  39. model->attack_state = FuzzerAttackStateIdle;
  40. furi_string_set_str(model->uid_str, "Not_set");
  41. },
  42. true);
  43. }
  44. void fuzzer_view_attack_set_uid(FuzzerViewAttack* view, const FuzzerPayload* uid) {
  45. furi_assert(view);
  46. furi_assert(uid->data);
  47. with_view_model(
  48. view->view,
  49. FuzzerViewAttackModel * model,
  50. {
  51. furi_string_printf(model->uid_str, "%02X", uid->data[0]);
  52. for(uint8_t i = 1; i < uid->data_size; i++) {
  53. furi_string_cat_printf(model->uid_str, ":%02X", uid->data[i]);
  54. }
  55. },
  56. true);
  57. }
  58. void fuzzer_view_update_state(FuzzerViewAttack* view, FuzzerAttackState state) {
  59. furi_assert(view);
  60. with_view_model(
  61. view->view, FuzzerViewAttackModel * model, { model->attack_state = state; }, true);
  62. }
  63. void fuzzer_view_attack_set_callback(
  64. FuzzerViewAttack* view_attack,
  65. FuzzerViewAttackCallback callback,
  66. void* context) {
  67. furi_assert(view_attack);
  68. view_attack->callback = callback;
  69. view_attack->context = context;
  70. }
  71. static void
  72. fuzzer_view_attack_draw_time_delays_line(Canvas* canvas, FuzzerViewAttackModel* model) {
  73. char temp_str[25];
  74. uint16_t crt;
  75. const uint16_t y = LINE_2_Y;
  76. canvas_set_font(canvas, FontPrimary);
  77. if(!model->td_emt_cursor) {
  78. canvas_set_font(canvas, FontSecondary);
  79. snprintf(temp_str, sizeof(temp_str), "Time delay:");
  80. canvas_draw_str_aligned(canvas, LEFT_RIGHT_OFFSET, y, AlignLeft, AlignBottom, temp_str);
  81. crt = canvas_string_width(canvas, temp_str);
  82. canvas_set_font(canvas, FontPrimary);
  83. snprintf(
  84. temp_str, sizeof(temp_str), "%d.%d", model->time_delay / 10, model->time_delay % 10);
  85. canvas_draw_str_aligned(
  86. canvas, crt + LEFT_RIGHT_OFFSET + 3, y, AlignLeft, AlignBottom, temp_str);
  87. canvas_set_font(canvas, FontSecondary);
  88. snprintf(
  89. temp_str, sizeof(temp_str), "EmT: %d.%d", model->emu_time / 10, model->emu_time % 10);
  90. canvas_draw_str_aligned(
  91. canvas, 128 - LEFT_RIGHT_OFFSET, y, AlignRight, AlignBottom, temp_str);
  92. } else {
  93. canvas_set_font(canvas, FontSecondary);
  94. snprintf(
  95. temp_str,
  96. sizeof(temp_str),
  97. "TD: %d.%d",
  98. model->time_delay / 10,
  99. model->time_delay % 10);
  100. canvas_draw_str_aligned(canvas, LEFT_RIGHT_OFFSET, y, AlignLeft, AlignBottom, temp_str);
  101. canvas_set_font(canvas, FontPrimary);
  102. snprintf(temp_str, sizeof(temp_str), "%d.%d", model->emu_time / 10, model->emu_time % 10);
  103. canvas_draw_str_aligned(
  104. canvas, 128 - LEFT_RIGHT_OFFSET, y, AlignRight, AlignBottom, temp_str);
  105. crt = canvas_string_width(canvas, temp_str);
  106. canvas_set_font(canvas, FontSecondary);
  107. snprintf(temp_str, sizeof(temp_str), "Emulation time:");
  108. canvas_draw_str_aligned(
  109. canvas, 128 - LEFT_RIGHT_OFFSET - crt - 3, y, AlignRight, AlignBottom, temp_str);
  110. }
  111. }
  112. static void fuzzer_view_attack_draw_time_delays_str(Canvas* canvas, FuzzerViewAttackModel* model) {
  113. char temp_str[20];
  114. uint16_t crt;
  115. const uint16_t y = LINE_2_Y;
  116. canvas_set_font(canvas, FontSecondary);
  117. snprintf(
  118. temp_str,
  119. sizeof(temp_str),
  120. "TD: %d.%d Emt: %d.%d",
  121. model->time_delay / 10,
  122. model->time_delay % 10,
  123. model->emu_time / 10,
  124. model->emu_time % 10);
  125. crt = canvas_string_width(canvas, temp_str);
  126. canvas_draw_str_aligned(
  127. canvas, 128 - LEFT_RIGHT_OFFSET - crt, y, AlignLeft, AlignBottom, temp_str);
  128. }
  129. static void fuzzer_view_attack_draw_idle(Canvas* canvas, FuzzerViewAttackModel* model) {
  130. if(model->td_emt_cursor) {
  131. elements_button_center(canvas, "Start");
  132. elements_button_left(canvas, "EmT -");
  133. elements_button_right(canvas, "+ EmT");
  134. } else {
  135. elements_button_center(canvas, "Start");
  136. elements_button_left(canvas, "TD -");
  137. elements_button_right(canvas, "+ TD");
  138. }
  139. }
  140. static void fuzzer_view_attack_draw_running(Canvas* canvas, FuzzerViewAttackModel* model) {
  141. UNUSED(model);
  142. elements_button_left(canvas, "Stop");
  143. elements_button_center(canvas, "Pause");
  144. }
  145. static void fuzzer_view_attack_draw_end(Canvas* canvas, FuzzerViewAttackModel* model) {
  146. UNUSED(model);
  147. // elements_button_center(canvas, "Restart"); // Reset
  148. elements_button_left(canvas, "Exit");
  149. }
  150. void fuzzer_view_attack_draw(Canvas* canvas, FuzzerViewAttackModel* model) {
  151. canvas_clear(canvas);
  152. canvas_set_color(canvas, ColorBlack);
  153. // Header - Attack name
  154. canvas_set_font(canvas, FontPrimary);
  155. canvas_draw_str_aligned(canvas, 64, LINE_1_Y, AlignCenter, AlignBottom, model->attack_name);
  156. // Time delays line or Status line
  157. switch(model->attack_state) {
  158. case FuzzerAttackStateIdle:
  159. fuzzer_view_attack_draw_time_delays_line(canvas, model);
  160. break;
  161. case FuzzerAttackStateAttacking:
  162. canvas_set_font(canvas, FontPrimary);
  163. canvas_draw_str(canvas, LEFT_RIGHT_OFFSET, LINE_2_Y, "Attacking");
  164. fuzzer_view_attack_draw_time_delays_str(canvas, model);
  165. break;
  166. case FuzzerAttackStateEmulating:
  167. canvas_set_font(canvas, FontPrimary);
  168. canvas_draw_str_aligned(canvas, 64, LINE_2_Y, AlignCenter, AlignBottom, "Emulating:");
  169. break;
  170. case FuzzerAttackStatePause:
  171. canvas_set_font(canvas, FontPrimary);
  172. canvas_draw_str(canvas, LEFT_RIGHT_OFFSET, LINE_2_Y, "Paused");
  173. canvas_set_font(canvas, FontSecondary);
  174. canvas_draw_icon_ex(canvas, 62, LINE_2_Y - 9, &I_Pin_arrow_up_7x9, IconRotation180);
  175. canvas_draw_icon(canvas, 69, LINE_2_Y - 9, &I_Pin_arrow_up_7x9);
  176. canvas_draw_str(canvas, 79, LINE_2_Y, "Change UID");
  177. break;
  178. case FuzzerAttackStateEnd:
  179. canvas_set_font(canvas, FontPrimary);
  180. canvas_draw_str_aligned(canvas, 64, LINE_2_Y, AlignCenter, AlignBottom, "Attack is over");
  181. break;
  182. default:
  183. break;
  184. }
  185. // Protocol name
  186. canvas_set_font(canvas, FontSecondary);
  187. canvas_draw_str_aligned(canvas, 64, LINE_3_Y, AlignCenter, AlignBottom, model->protocol_name);
  188. // Current UID
  189. canvas_set_font(canvas, FontPrimary);
  190. if(128 < canvas_string_width(canvas, furi_string_get_cstr(model->uid_str))) {
  191. canvas_set_font(canvas, FontSecondary);
  192. }
  193. canvas_draw_str_aligned(
  194. canvas, 64, LINE_4_Y, AlignCenter, AlignBottom, furi_string_get_cstr(model->uid_str));
  195. // Btns
  196. canvas_set_font(canvas, FontSecondary);
  197. if(model->attack_state == FuzzerAttackStateAttacking ||
  198. model->attack_state == FuzzerAttackStateEmulating) {
  199. fuzzer_view_attack_draw_running(canvas, model);
  200. } else if(model->attack_state == FuzzerAttackStateIdle) {
  201. fuzzer_view_attack_draw_idle(canvas, model);
  202. } else if(model->attack_state == FuzzerAttackStatePause) {
  203. elements_button_left(canvas, "Back");
  204. elements_button_right(canvas, "Save");
  205. elements_button_center(canvas, "Emu");
  206. } else if(model->attack_state == FuzzerAttackStateEnd) {
  207. fuzzer_view_attack_draw_end(canvas, model);
  208. }
  209. }
  210. static bool fuzzer_view_attack_input_idle(
  211. FuzzerViewAttack* view_attack,
  212. InputEvent* event,
  213. FuzzerViewAttackModel* model) {
  214. if(event->key == InputKeyBack && event->type == InputTypeShort) {
  215. view_attack->callback(FuzzerCustomEventViewAttackExit, view_attack->context);
  216. return true;
  217. } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  218. view_attack->callback(FuzzerCustomEventViewAttackRunAttack, view_attack->context);
  219. return true;
  220. } else if(event->key == InputKeyLeft) {
  221. if(!model->td_emt_cursor) {
  222. // TimeDelay --
  223. if(event->type == InputTypeShort) {
  224. if(model->time_delay > model->time_delay_min) {
  225. model->time_delay--;
  226. }
  227. } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) {
  228. if((model->time_delay - 10) >= model->time_delay_min) {
  229. model->time_delay -= 10;
  230. } else {
  231. model->time_delay = model->time_delay_min;
  232. }
  233. }
  234. } else {
  235. // EmuTime --
  236. if(event->type == InputTypeShort) {
  237. if(model->emu_time > model->emu_time_min) {
  238. model->emu_time--;
  239. }
  240. } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) {
  241. if((model->emu_time - 10) >= model->emu_time_min) {
  242. model->emu_time -= 10;
  243. } else {
  244. model->emu_time = model->emu_time_min;
  245. }
  246. }
  247. }
  248. return true;
  249. } else if(event->key == InputKeyRight) {
  250. if(!model->td_emt_cursor) {
  251. // TimeDelay ++
  252. if(event->type == InputTypeShort) {
  253. if(model->time_delay < FUZZ_TIME_DELAY_MAX) {
  254. model->time_delay++;
  255. }
  256. } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) {
  257. model->time_delay += 10;
  258. if(model->time_delay > FUZZ_TIME_DELAY_MAX) {
  259. model->time_delay = FUZZ_TIME_DELAY_MAX;
  260. }
  261. }
  262. } else {
  263. // EmuTime ++
  264. if(event->type == InputTypeShort) {
  265. if(model->emu_time < FUZZ_TIME_DELAY_MAX) {
  266. model->emu_time++;
  267. }
  268. } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) {
  269. model->emu_time += 10;
  270. if(model->emu_time > FUZZ_TIME_DELAY_MAX) {
  271. model->emu_time = FUZZ_TIME_DELAY_MAX;
  272. }
  273. }
  274. }
  275. return true;
  276. } else if(
  277. (event->key == InputKeyUp || event->key == InputKeyDown) &&
  278. event->type == InputTypeShort) {
  279. with_view_model(
  280. view_attack->view,
  281. FuzzerViewAttackModel * model,
  282. { model->td_emt_cursor = !model->td_emt_cursor; },
  283. true);
  284. return true;
  285. }
  286. return true;
  287. }
  288. static bool fuzzer_view_attack_input_end(
  289. FuzzerViewAttack* view_attack,
  290. InputEvent* event,
  291. FuzzerViewAttackModel* model) {
  292. UNUSED(model);
  293. if((event->key == InputKeyBack || event->key == InputKeyLeft) &&
  294. event->type == InputTypeShort) {
  295. // Exit if Ended
  296. view_attack->callback(FuzzerCustomEventViewAttackExit, view_attack->context);
  297. }
  298. return true;
  299. }
  300. bool fuzzer_view_attack_input(InputEvent* event, void* context) {
  301. furi_assert(context);
  302. FuzzerViewAttack* view_attack = context;
  303. // if(event->key == InputKeyBack && event->type == InputTypeShort) {
  304. // view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context);
  305. // return true;
  306. // } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  307. // view_attack->callback(FuzzerCustomEventViewAttackOk, view_attack->context);
  308. // return true;
  309. // } else
  310. // {
  311. with_view_model(
  312. view_attack->view,
  313. FuzzerViewAttackModel * model,
  314. {
  315. switch(model->attack_state) {
  316. case FuzzerAttackStateIdle:
  317. fuzzer_view_attack_input_idle(view_attack, event, model);
  318. break;
  319. case FuzzerAttackStateEnd:
  320. fuzzer_view_attack_input_end(view_attack, event, model);
  321. break;
  322. case FuzzerAttackStateAttacking:
  323. case FuzzerAttackStateEmulating:
  324. if((event->key == InputKeyBack || event->key == InputKeyLeft) &&
  325. event->type == InputTypeShort) {
  326. view_attack->callback(FuzzerCustomEventViewAttackIdle, view_attack->context);
  327. } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  328. view_attack->callback(FuzzerCustomEventViewAttackPause, view_attack->context);
  329. }
  330. break;
  331. case FuzzerAttackStatePause:
  332. if((event->key == InputKeyBack || event->key == InputKeyLeft) &&
  333. event->type == InputTypeShort) {
  334. view_attack->callback(FuzzerCustomEventViewAttackIdle, view_attack->context);
  335. } else if(event->key == InputKeyRight && event->type == InputTypeShort) {
  336. view_attack->callback(FuzzerCustomEventViewAttackSave, view_attack->context);
  337. } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  338. view_attack->callback(
  339. FuzzerCustomEventViewAttackEmulateCurrent, view_attack->context);
  340. } else if(event->key == InputKeyUp && event->type == InputTypeShort) {
  341. view_attack->callback(
  342. FuzzerCustomEventViewAttackPrevUid, view_attack->context);
  343. } else if(event->key == InputKeyDown && event->type == InputTypeShort) {
  344. view_attack->callback(
  345. FuzzerCustomEventViewAttackNextUid, view_attack->context);
  346. }
  347. break;
  348. default:
  349. break;
  350. }
  351. },
  352. true);
  353. // }
  354. return true;
  355. }
  356. void fuzzer_view_attack_enter(void* context) {
  357. furi_assert(context);
  358. }
  359. void fuzzer_view_attack_exit(void* context) {
  360. furi_assert(context);
  361. FuzzerViewAttack* view_attack = context;
  362. with_view_model(
  363. view_attack->view, FuzzerViewAttackModel * model, { model->td_emt_cursor = false; }, true);
  364. }
  365. FuzzerViewAttack* fuzzer_view_attack_alloc() {
  366. if(fuzzer_proto_get_max_data_size() > UID_MAX_DISPLAYED_LEN) {
  367. furi_crash("Maximum of displayed bytes exceeded");
  368. }
  369. FuzzerViewAttack* view_attack = malloc(sizeof(FuzzerViewAttack));
  370. // View allocation and configuration
  371. view_attack->view = view_alloc();
  372. view_allocate_model(view_attack->view, ViewModelTypeLocking, sizeof(FuzzerViewAttackModel));
  373. view_set_context(view_attack->view, view_attack);
  374. view_set_draw_callback(view_attack->view, (ViewDrawCallback)fuzzer_view_attack_draw);
  375. view_set_input_callback(view_attack->view, fuzzer_view_attack_input);
  376. view_set_enter_callback(view_attack->view, fuzzer_view_attack_enter);
  377. view_set_exit_callback(view_attack->view, fuzzer_view_attack_exit);
  378. with_view_model(
  379. view_attack->view,
  380. FuzzerViewAttackModel * model,
  381. {
  382. model->time_delay = fuzzer_proto_get_def_idle_time();
  383. model->time_delay_min = 1; // model->time_delay;
  384. model->emu_time = fuzzer_proto_get_def_emu_time();
  385. model->emu_time_min = 2; // model->emu_time;
  386. model->uid_str = furi_string_alloc_set_str("Not_set");
  387. // malloc(ATTACK_SCENE_MAX_UID_LENGTH + 1);
  388. model->attack_state = FuzzerAttackStateOff;
  389. model->td_emt_cursor = false;
  390. // strcpy(model->uid_str, "Not_set");
  391. model->attack_name = "Not_set";
  392. model->protocol_name = "Not_set";
  393. },
  394. true);
  395. return view_attack;
  396. }
  397. void fuzzer_view_attack_free(FuzzerViewAttack* view_attack) {
  398. furi_assert(view_attack);
  399. with_view_model(
  400. view_attack->view,
  401. FuzzerViewAttackModel * model,
  402. { furi_string_free(model->uid_str); },
  403. true);
  404. view_free(view_attack->view);
  405. free(view_attack);
  406. }
  407. View* fuzzer_view_attack_get_view(FuzzerViewAttack* view_attack) {
  408. furi_assert(view_attack);
  409. return view_attack->view;
  410. }
  411. uint8_t fuzzer_view_attack_get_time_delay(FuzzerViewAttack* view) {
  412. furi_assert(view);
  413. uint8_t time_delay;
  414. with_view_model(
  415. view->view, FuzzerViewAttackModel * model, { time_delay = model->time_delay; }, false);
  416. return time_delay;
  417. }
  418. uint8_t fuzzer_view_attack_get_emu_time(FuzzerViewAttack* view) {
  419. furi_assert(view);
  420. uint8_t emu_time;
  421. with_view_model(
  422. view->view, FuzzerViewAttackModel * model, { emu_time = model->emu_time; }, false);
  423. return emu_time;
  424. }