subbrute_scene_run_attack.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. #include "subbrute_scene_run_attack.h"
  2. #include <lib/subghz/transmitter.h>
  3. #include <gui/elements.h>
  4. //uint64_t subbrute_counter = 0;
  5. uint64_t max_value;
  6. bool locked = false;
  7. bool toSave = false;
  8. char subbrute_payload_byte[4];
  9. #define SUBBRUTE_DELAY 1
  10. FuriHalSubGhzPreset str_to_preset(string_t preset) {
  11. if(string_cmp_str(preset, "FuriHalSubGhzPresetOok270Async") == 0) {
  12. return FuriHalSubGhzPresetOok270Async;
  13. }
  14. if(string_cmp_str(preset, "FuriHalSubGhzPresetOok650Async") == 0) {
  15. return FuriHalSubGhzPresetOok650Async;
  16. }
  17. if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev238Async") == 0) {
  18. return FuriHalSubGhzPreset2FSKDev238Async;
  19. }
  20. if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev476Async") == 0) {
  21. return FuriHalSubGhzPreset2FSKDev476Async;
  22. }
  23. if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) {
  24. return FuriHalSubGhzPresetMSK99_97KbAsync;
  25. }
  26. if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) {
  27. return FuriHalSubGhzPresetMSK99_97KbAsync;
  28. }
  29. return FuriHalSubGhzPresetCustom;
  30. }
  31. void subbrute_emit(SubBruteState* context) {
  32. //FURI_LOG_D(TAG, string_get_cstr(context->flipper_format_string));
  33. context->transmitter =
  34. subghz_transmitter_alloc_init(context->environment, string_get_cstr(context->protocol));
  35. subghz_transmitter_deserialize(context->transmitter, context->flipper_format);
  36. furi_hal_subghz_reset();
  37. furi_hal_subghz_load_preset(str_to_preset(context->preset));
  38. context->frequency_cal = furi_hal_subghz_set_frequency_and_path(context->frequency);
  39. furi_hal_subghz_start_async_tx(subghz_transmitter_yield, context->transmitter);
  40. while(!(furi_hal_subghz_is_async_tx_complete())) {
  41. furi_delay_ms(1);
  42. }
  43. furi_hal_subghz_stop_async_tx();
  44. subghz_transmitter_stop(context->transmitter);
  45. furi_hal_subghz_idle();
  46. subghz_transmitter_free(context->transmitter);
  47. }
  48. void prepare_emit(SubBruteState* context) {
  49. UNUSED(context);
  50. furi_hal_subghz_init();
  51. }
  52. void clear_emit(SubBruteState* context) {
  53. UNUSED(context);
  54. //furi_hal_subghz_stop_async_tx();
  55. //furi_hal_subghz_idle();
  56. furi_hal_subghz_sleep();
  57. }
  58. /*
  59. void subbrute_send_raw_packet(SubBruteState* context) {
  60. string_reset(context->candidate);
  61. // Payload to padded binary string
  62. int* binaryNum = (int*)malloc(sizeof(int) * context->bit);
  63. uint32_t i = 0;
  64. for(i = 0; i < context->bit; i++) {
  65. binaryNum[i] = 0;
  66. }
  67. i = 0;
  68. uint64_t counter = context->payload;
  69. while(counter > 0) {
  70. binaryNum[i] = counter % 2;
  71. counter = counter / 2;
  72. i++;
  73. }
  74. // printing binary array in reverse order and build raw payload
  75. for(uint32_t loop = 0; loop < context->repeat; loop++) {
  76. for(int j = (int)context->bit - 1; j >= 0; j--) {
  77. if(binaryNum[j] == 1) {
  78. string_cat(context->candidate, context->subbrute_raw_one);
  79. } else {
  80. string_cat(context->candidate, context->subbrute_raw_zero);
  81. }
  82. }
  83. string_cat(context->candidate, context->subbrute_raw_stop);
  84. }
  85. free(binaryNum);
  86. string_init_printf(
  87. context->flipper_format_string,
  88. "Filetype: Flipper SubGhz RAW File\n"
  89. "Version: 1\n"
  90. "Frequency: %d\n"
  91. "Preset: %s\n"
  92. "Protocol: RAW\n"
  93. "RAW_Data: %s",
  94. context->frequency,
  95. string_get_cstr(context->preset),
  96. string_get_cstr(context->candidate));
  97. subbrute_emit(context);
  98. }
  99. */
  100. void subbrute_send_packet_parsed(SubBruteState* context) {
  101. if(context->attack == SubBruteAttackLoadFile) {
  102. snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)context->payload);
  103. string_replace_at(context->candidate, context->str_index, 3, subbrute_payload_byte);
  104. } else {
  105. string_t buffer;
  106. string_init(buffer);
  107. string_init_printf(buffer, "%16X", context->payload);
  108. int j = 0;
  109. string_set_str(context->candidate, " ");
  110. for(uint8_t i = 0; i < 16; i++) {
  111. if(string_get_char(buffer, i) != ' ') {
  112. string_set_char(context->candidate, i + j, string_get_char(buffer, i));
  113. } else {
  114. string_set_char(context->candidate, i + j, '0');
  115. }
  116. if(i % 2 != 0) {
  117. j++;
  118. }
  119. }
  120. string_clear(buffer);
  121. }
  122. if(strcmp(string_get_cstr(context->protocol), "Princeton") == 0) {
  123. string_init_printf(
  124. context->flipper_format_string,
  125. "Filetype: Flipper SubGhz Key File\n"
  126. "Version: 1\n"
  127. "Frequency: %u\n"
  128. "Preset: %s\n"
  129. "Protocol: %s\n"
  130. "Bit: %d\n"
  131. "Key: %s\n"
  132. "TE: %d\n",
  133. context->frequency,
  134. string_get_cstr(context->preset),
  135. string_get_cstr(context->protocol),
  136. context->bit,
  137. string_get_cstr(context->candidate),
  138. context->te);
  139. } else {
  140. string_init_printf(
  141. context->flipper_format_string,
  142. "Filetype: Flipper SubGhz Key File\n"
  143. "Version: 1\n"
  144. "Frequency: %u\n"
  145. "Preset: %s\n"
  146. "Protocol: %s\n"
  147. "Bit: %d\n"
  148. "Key: %s\n",
  149. context->frequency,
  150. string_get_cstr(context->preset),
  151. string_get_cstr(context->protocol),
  152. context->bit,
  153. string_get_cstr(context->candidate));
  154. }
  155. stream_clean(context->stream);
  156. stream_write_string(context->stream, context->flipper_format_string);
  157. }
  158. void subbrute_send_packet(SubBruteState* context) {
  159. ///if(string_cmp_str(context->protocol, "RAW") == 0) {
  160. // subbrute_send_raw_packet(context);
  161. //} else {
  162. subbrute_send_packet_parsed(context);
  163. subbrute_emit(context);
  164. //}
  165. string_clear(context->flipper_format_string);
  166. }
  167. void subbrute_scene_run_attack_on_exit(SubBruteState* context) {
  168. if(!toSave) {
  169. clear_emit(context);
  170. furi_thread_free(context->bruthread);
  171. flipper_format_free(context->flipper_format);
  172. subghz_receiver_free(context->receiver);
  173. subghz_environment_free(context->environment);
  174. }
  175. }
  176. void subbrute_scene_run_attack_on_tick(SubBruteState* context) {
  177. if(!context->is_attacking || locked) {
  178. return;
  179. }
  180. //if(0 != subbrute_counter) {
  181. locked = true;
  182. subbrute_send_packet(context);
  183. if(context->payload == max_value) {
  184. //context->payload = 0x00;
  185. //subbrute_counter = 0;
  186. context->is_attacking = false;
  187. notification_message(context->notify, &sequence_blink_stop);
  188. notification_message(context->notify, &sequence_single_vibro);
  189. } else {
  190. context->payload++;
  191. }
  192. locked = false;
  193. //}
  194. /*if(subbrute_counter > SUBBRUTE_DELAY) {
  195. subbrute_counter = 0;
  196. } else {
  197. subbrute_counter++;
  198. }*/
  199. }
  200. void subbrute_run_timer(SubBruteState* context) {
  201. while(true) {
  202. if(!context->is_attacking) {
  203. context->is_thread_running = false;
  204. break;
  205. }
  206. //furi_delay_ms(10);
  207. subbrute_scene_run_attack_on_tick(context);
  208. }
  209. }
  210. // entrypoint for worker
  211. static int32_t subbrute_worker_thread(void* ctx) {
  212. SubBruteState* app = ctx;
  213. subbrute_run_timer(app);
  214. return 0;
  215. }
  216. void start_bruthread(SubBruteState* app) {
  217. if(!app->is_thread_running) {
  218. furi_thread_start(app->bruthread);
  219. app->is_thread_running = true;
  220. }
  221. }
  222. void subbrute_scene_run_attack_on_enter(SubBruteState* context) {
  223. if(!toSave) {
  224. if(context->attack == SubBruteAttackLoadFile) {
  225. max_value = 0xFF;
  226. } else {
  227. string_t max_value_s;
  228. string_init(max_value_s);
  229. for(uint8_t i = 0; i < context->bit; i++) {
  230. string_cat_printf(max_value_s, "1");
  231. }
  232. max_value = (uint64_t)strtol(string_get_cstr(max_value_s), NULL, 2);
  233. string_clear(max_value_s);
  234. }
  235. context->str_index = (context->key_index * 3);
  236. string_init_set(context->candidate, context->key);
  237. context->flipper_format = flipper_format_string_alloc();
  238. context->stream = flipper_format_get_raw_stream(context->flipper_format);
  239. context->environment = subghz_environment_alloc();
  240. context->receiver = subghz_receiver_alloc_init(context->environment);
  241. subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable);
  242. prepare_emit(context);
  243. context->bruthread = furi_thread_alloc();
  244. furi_thread_set_name(context->bruthread, "SubBrute Worker");
  245. furi_thread_set_stack_size(context->bruthread, 2048);
  246. furi_thread_set_context(context->bruthread, context);
  247. furi_thread_set_callback(context->bruthread, subbrute_worker_thread);
  248. } else {
  249. toSave = false;
  250. }
  251. }
  252. void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context) {
  253. if(event.evt_type == EventTypeKey) {
  254. if(event.input_type == InputTypeShort) {
  255. switch(event.key) {
  256. case InputKeyDown:
  257. break;
  258. case InputKeyUp:
  259. if(!context->is_attacking) {
  260. subbrute_send_packet_parsed(context);
  261. string_clear(context->flipper_format_string);
  262. toSave = true;
  263. context->current_scene = SceneSaveName;
  264. }
  265. break;
  266. case InputKeyLeft:
  267. if(!context->is_attacking && context->payload > 0x00) {
  268. context->payload--;
  269. subbrute_send_packet(context);
  270. notification_message(context->notify, &sequence_blink_blue_10);
  271. } else if(!context->is_attacking && context->payload == 0x00) {
  272. context->payload = max_value;
  273. subbrute_send_packet(context);
  274. notification_message(context->notify, &sequence_blink_blue_10);
  275. }
  276. break;
  277. case InputKeyRight:
  278. if(!context->is_attacking && context->payload < max_value) {
  279. context->payload++;
  280. subbrute_send_packet(context);
  281. notification_message(context->notify, &sequence_blink_blue_10);
  282. } else if(!context->is_attacking && context->payload == max_value) {
  283. context->payload = 0x00;
  284. subbrute_send_packet(context);
  285. notification_message(context->notify, &sequence_blink_blue_10);
  286. }
  287. break;
  288. case InputKeyOk:
  289. if(!context->is_attacking) {
  290. if(context->payload == max_value) {
  291. context->payload = 0x00;
  292. //subbrute_counter = 0;
  293. }
  294. context->is_attacking = true;
  295. start_bruthread(context);
  296. notification_message(context->notify, &sequence_blink_start_blue);
  297. } else {
  298. context->is_attacking = false;
  299. //context->close_thread_please = true;
  300. if(context->is_thread_running && context->bruthread) {
  301. furi_thread_join(context->bruthread); // wait until thread is finished
  302. }
  303. //context->close_thread_please = false;
  304. notification_message(context->notify, &sequence_blink_stop);
  305. notification_message(context->notify, &sequence_single_vibro);
  306. }
  307. break;
  308. case InputKeyBack:
  309. locked = false;
  310. //context->close_thread_please = true;
  311. context->is_attacking = false;
  312. if(context->is_thread_running && context->bruthread) {
  313. furi_thread_join(context->bruthread); // wait until thread is finished
  314. }
  315. //context->close_thread_please = false;
  316. string_reset(context->notification_msg);
  317. context->payload = 0x00;
  318. //subbrute_counter = 0;
  319. notification_message(context->notify, &sequence_blink_stop);
  320. if(context->attack == SubBruteAttackLoadFile) {
  321. context->current_scene = SceneSelectField;
  322. } else {
  323. context->current_scene = SceneEntryPoint;
  324. }
  325. break;
  326. }
  327. }
  328. }
  329. }
  330. void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context) {
  331. canvas_clear(canvas);
  332. canvas_set_color(canvas, ColorBlack);
  333. // Frame
  334. //canvas_draw_frame(canvas, 0, 0, 128, 64);
  335. // Title
  336. canvas_set_font(canvas, FontPrimary);
  337. canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignTop, "Fire in the hole!");
  338. char msg_index[26];
  339. snprintf(
  340. msg_index, sizeof(msg_index), "< %04d / %04d >", (int)context->payload, (int)max_value);
  341. canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, msg_index);
  342. canvas_set_font(canvas, FontSecondary);
  343. char start_stop_msg[20];
  344. snprintf(start_stop_msg, sizeof(start_stop_msg), " Press (^) to save ");
  345. if(context->is_attacking) {
  346. elements_button_center(canvas, "Stop");
  347. } else {
  348. elements_button_center(canvas, "Start");
  349. }
  350. canvas_draw_str_aligned(canvas, 64, 39, AlignCenter, AlignTop, start_stop_msg);
  351. }