subbrute_worker.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #include "subbrute_worker_private.h"
  2. #include <string.h>
  3. #include <toolbox/stream/stream.h>
  4. #include <flipper_format.h>
  5. #include <flipper_format_i.h>
  6. #define TAG "SubBruteWorker"
  7. #define SUBBRUTE_TX_TIMEOUT 5
  8. #define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
  9. SubBruteWorker* subbrute_worker_alloc() {
  10. SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
  11. instance->state = SubBruteWorkerStateIDLE;
  12. instance->step = 0;
  13. instance->worker_running = false;
  14. instance->initiated = false;
  15. instance->last_time_tx_data = 0;
  16. instance->load_index = 0;
  17. instance->thread = furi_thread_alloc();
  18. furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
  19. furi_thread_set_stack_size(instance->thread, 2048);
  20. furi_thread_set_context(instance->thread, instance);
  21. furi_thread_set_callback(instance->thread, subbrute_worker_thread);
  22. instance->context = NULL;
  23. instance->callback = NULL;
  24. instance->decoder_result = NULL;
  25. instance->transmitter = NULL;
  26. instance->environment = subghz_environment_alloc();
  27. instance->transmit_mode = false;
  28. return instance;
  29. }
  30. void subbrute_worker_free(SubBruteWorker* instance) {
  31. furi_assert(instance);
  32. // I don't know how to free this
  33. instance->decoder_result = NULL;
  34. if(instance->transmitter != NULL) {
  35. subghz_transmitter_free(instance->transmitter);
  36. instance->transmitter = NULL;
  37. }
  38. subghz_environment_free(instance->environment);
  39. instance->environment = NULL;
  40. furi_thread_free(instance->thread);
  41. free(instance);
  42. }
  43. uint64_t subbrute_worker_get_step(SubBruteWorker* instance) {
  44. return instance->step;
  45. }
  46. bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step) {
  47. furi_assert(instance);
  48. if(!subbrute_worker_can_manual_transmit(instance)) {
  49. FURI_LOG_W(TAG, "Cannot set step during running mode");
  50. return false;
  51. }
  52. instance->step = step;
  53. return true;
  54. }
  55. bool subbrute_worker_init_default_attack(
  56. SubBruteWorker* instance,
  57. SubBruteAttacks attack_type,
  58. uint64_t step,
  59. const SubBruteProtocol* protocol) {
  60. furi_assert(instance);
  61. if(instance->worker_running) {
  62. FURI_LOG_W(TAG, "Init Worker when it's running");
  63. subbrute_worker_stop(instance);
  64. }
  65. instance->attack = attack_type;
  66. instance->frequency = protocol->frequency;
  67. instance->preset = protocol->preset;
  68. instance->file = protocol->file;
  69. instance->step = step;
  70. instance->bits = protocol->bits;
  71. instance->te = protocol->te;
  72. instance->repeat = protocol->repeat;
  73. instance->load_index = 0;
  74. instance->file_key = NULL;
  75. instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
  76. instance->initiated = true;
  77. instance->state = SubBruteWorkerStateReady;
  78. subbrute_worker_send_callback(instance);
  79. #ifdef FURI_DEBUG
  80. FURI_LOG_I(
  81. TAG,
  82. "subbrute_worker_init_default_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
  83. subbrute_protocol_name(instance->attack),
  84. instance->bits,
  85. subbrute_protocol_preset(instance->preset),
  86. subbrute_protocol_file(instance->file),
  87. instance->te,
  88. instance->repeat,
  89. instance->max_value);
  90. #endif
  91. return true;
  92. }
  93. bool subbrute_worker_init_file_attack(
  94. SubBruteWorker* instance,
  95. uint64_t step,
  96. uint8_t load_index,
  97. const char* file_key,
  98. SubBruteProtocol* protocol) {
  99. furi_assert(instance);
  100. if(instance->worker_running) {
  101. FURI_LOG_W(TAG, "Init Worker when it's running");
  102. subbrute_worker_stop(instance);
  103. }
  104. instance->attack = SubBruteAttackLoadFile;
  105. instance->frequency = protocol->frequency;
  106. instance->preset = protocol->preset;
  107. instance->file = protocol->file;
  108. instance->step = step;
  109. instance->bits = protocol->bits;
  110. instance->te = protocol->te;
  111. instance->load_index = load_index;
  112. instance->repeat = protocol->repeat;
  113. instance->file_key = file_key;
  114. instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
  115. instance->initiated = true;
  116. instance->state = SubBruteWorkerStateReady;
  117. subbrute_worker_send_callback(instance);
  118. #ifdef FURI_DEBUG
  119. FURI_LOG_I(
  120. TAG,
  121. "subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
  122. subbrute_protocol_name(instance->attack),
  123. instance->bits,
  124. subbrute_protocol_preset(instance->preset),
  125. subbrute_protocol_file(instance->file),
  126. instance->te,
  127. instance->repeat,
  128. instance->max_value);
  129. #endif
  130. return true;
  131. }
  132. bool subbrute_worker_start(SubBruteWorker* instance) {
  133. furi_assert(instance);
  134. if(!instance->initiated) {
  135. FURI_LOG_W(TAG, "Worker not init!");
  136. return false;
  137. }
  138. if(instance->worker_running) {
  139. FURI_LOG_W(TAG, "Worker is already running!");
  140. return false;
  141. }
  142. if(instance->state != SubBruteWorkerStateReady &&
  143. instance->state != SubBruteWorkerStateFinished) {
  144. FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
  145. return false;
  146. }
  147. instance->worker_running = true;
  148. furi_thread_start(instance->thread);
  149. return true;
  150. }
  151. void subbrute_worker_stop(SubBruteWorker* instance) {
  152. furi_assert(instance);
  153. instance->worker_running = false;
  154. furi_thread_join(instance->thread);
  155. furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
  156. furi_hal_subghz_sleep();
  157. }
  158. bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step) {
  159. furi_assert(instance);
  160. if(!instance->initiated) {
  161. FURI_LOG_W(TAG, "Worker not init!");
  162. return false;
  163. }
  164. if(instance->worker_running) {
  165. FURI_LOG_W(TAG, "Worker in running state!");
  166. return false;
  167. }
  168. if(instance->state != SubBruteWorkerStateReady &&
  169. instance->state != SubBruteWorkerStateFinished) {
  170. FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
  171. return false;
  172. }
  173. uint32_t ticks = furi_get_tick();
  174. if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
  175. #if FURI_DEBUG
  176. FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
  177. #endif
  178. return false;
  179. }
  180. instance->last_time_tx_data = ticks;
  181. instance->step = step;
  182. bool result;
  183. instance->protocol_name = subbrute_protocol_file(instance->file);
  184. FlipperFormat* flipper_format = flipper_format_string_alloc();
  185. Stream* stream = flipper_format_get_raw_stream(flipper_format);
  186. stream_clean(stream);
  187. if(instance->attack == SubBruteAttackLoadFile) {
  188. subbrute_protocol_file_payload(
  189. stream,
  190. step,
  191. instance->bits,
  192. instance->te,
  193. instance->repeat,
  194. instance->load_index,
  195. instance->file_key);
  196. } else {
  197. subbrute_protocol_default_payload(
  198. stream, step, instance->bits, instance->te, instance->repeat);
  199. }
  200. // size_t written = stream_write_string(stream, payload);
  201. // if(written <= 0) {
  202. // FURI_LOG_W(TAG, "Error creating packet! EXIT");
  203. // result = false;
  204. // } else {
  205. subbrute_worker_subghz_transmit(instance, flipper_format);
  206. result = true;
  207. #if FURI_DEBUG
  208. FURI_LOG_D(TAG, "Manual transmit done");
  209. #endif
  210. // }
  211. flipper_format_free(flipper_format);
  212. // furi_string_free(payload);
  213. return result;
  214. }
  215. bool subbrute_worker_is_running(SubBruteWorker* instance) {
  216. return instance->worker_running;
  217. }
  218. bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance) {
  219. furi_assert(instance);
  220. if(!instance->initiated) {
  221. FURI_LOG_W(TAG, "Worker not init!");
  222. return false;
  223. }
  224. return !instance->worker_running && instance->state != SubBruteWorkerStateIDLE &&
  225. instance->state != SubBruteWorkerStateTx &&
  226. ((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
  227. }
  228. void subbrute_worker_set_callback(
  229. SubBruteWorker* instance,
  230. SubBruteWorkerCallback callback,
  231. void* context) {
  232. furi_assert(instance);
  233. instance->callback = callback;
  234. instance->context = context;
  235. }
  236. void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format) {
  237. while(instance->transmit_mode) {
  238. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  239. }
  240. instance->transmit_mode = true;
  241. if(instance->transmitter != NULL) {
  242. subghz_transmitter_free(instance->transmitter);
  243. instance->transmitter = NULL;
  244. }
  245. instance->transmitter =
  246. subghz_transmitter_alloc_init(instance->environment, instance->protocol_name);
  247. subghz_transmitter_deserialize(instance->transmitter, flipper_format);
  248. furi_hal_subghz_reset();
  249. furi_hal_subghz_load_preset(instance->preset);
  250. furi_hal_subghz_set_frequency_and_path(instance->frequency);
  251. furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
  252. while(!furi_hal_subghz_is_async_tx_complete()) {
  253. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  254. }
  255. furi_hal_subghz_stop_async_tx();
  256. furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
  257. furi_hal_subghz_sleep();
  258. subghz_transmitter_free(instance->transmitter);
  259. instance->transmitter = NULL;
  260. instance->transmit_mode = false;
  261. }
  262. void subbrute_worker_send_callback(SubBruteWorker* instance) {
  263. if(instance->callback != NULL) {
  264. instance->callback(instance->context, instance->state);
  265. }
  266. }
  267. /**
  268. * Entrypoint for worker
  269. *
  270. * @param context SubBruteWorker*
  271. * @return 0 if ok
  272. */
  273. int32_t subbrute_worker_thread(void* context) {
  274. furi_assert(context);
  275. SubBruteWorker* instance = (SubBruteWorker*)context;
  276. if(!instance->worker_running) {
  277. FURI_LOG_W(TAG, "Worker is not set to running state!");
  278. return -1;
  279. }
  280. if(instance->state != SubBruteWorkerStateReady &&
  281. instance->state != SubBruteWorkerStateFinished) {
  282. FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
  283. return -2;
  284. }
  285. #ifdef FURI_DEBUG
  286. FURI_LOG_I(TAG, "Worker start");
  287. #endif
  288. SubBruteWorkerState local_state = instance->state = SubBruteWorkerStateTx;
  289. subbrute_worker_send_callback(instance);
  290. instance->protocol_name = subbrute_protocol_file(instance->file);
  291. FlipperFormat* flipper_format = flipper_format_string_alloc();
  292. Stream* stream = flipper_format_get_raw_stream(flipper_format);
  293. while(instance->worker_running) {
  294. stream_clean(stream);
  295. if(instance->attack == SubBruteAttackLoadFile) {
  296. subbrute_protocol_file_payload(
  297. stream,
  298. instance->step,
  299. instance->bits,
  300. instance->te,
  301. instance->repeat,
  302. instance->load_index,
  303. instance->file_key);
  304. } else {
  305. subbrute_protocol_default_payload(
  306. stream, instance->step, instance->bits, instance->te, instance->repeat);
  307. }
  308. #ifdef FURI_DEBUG
  309. //FURI_LOG_I(TAG, "Payload: %s", furi_string_get_cstr(payload));
  310. //furi_delay_ms(SUBBRUTE_MANUAL_TRANSMIT_INTERVAL / 4);
  311. #endif
  312. // size_t written = stream_write_stream_write_string(stream, payload);
  313. // if(written <= 0) {
  314. // FURI_LOG_W(TAG, "Error creating packet! BREAK");
  315. // instance->worker_running = false;
  316. // local_state = SubBruteWorkerStateIDLE;
  317. // furi_string_free(payload);
  318. // break;
  319. // }
  320. subbrute_worker_subghz_transmit(instance, flipper_format);
  321. if(instance->step + 1 > instance->max_value) {
  322. #ifdef FURI_DEBUG
  323. FURI_LOG_I(TAG, "Worker finished to end");
  324. #endif
  325. local_state = SubBruteWorkerStateFinished;
  326. // furi_string_free(payload);
  327. break;
  328. }
  329. instance->step++;
  330. // furi_string_free(payload);
  331. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  332. }
  333. flipper_format_free(flipper_format);
  334. instance->worker_running = false; // Because we have error states
  335. instance->state = local_state == SubBruteWorkerStateTx ? SubBruteWorkerStateReady :
  336. local_state;
  337. subbrute_worker_send_callback(instance);
  338. #ifdef FURI_DEBUG
  339. FURI_LOG_I(TAG, "Worker stop");
  340. #endif
  341. return 0;
  342. }