subbrute_worker.c 11 KB

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