fake_worker.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. #include "fake_worker.h"
  2. #include "helpers/hardware_worker.h"
  3. #include "protocol_i.h"
  4. #include <timer.h>
  5. #include <lib/toolbox/hex.h>
  6. #include <toolbox/stream/stream.h>
  7. #include <toolbox/stream/buffered_file_stream.h>
  8. #define TAG "Fuzzer worker"
  9. #define TOTAL_PROTOCOL_COUNT COUNT_OF(&fuzzer_proto_items)
  10. typedef uint8_t FuzzerWorkerPayload[MAX_PAYLOAD_SIZE];
  11. struct FuzzerWorker {
  12. HardwareWorker* hw_worker;
  13. const FuzzerProtocol* protocol;
  14. HwProtocolID* suported_proto;
  15. FuzzerWorkerPayload payload;
  16. FuzzerWorkerAttackType attack_type;
  17. uint16_t index;
  18. Stream* uids_stream;
  19. uint8_t chusen_byte;
  20. bool treead_running;
  21. bool in_emu_phase;
  22. FuriTimer* timer;
  23. uint16_t timer_idle_time_ms;
  24. uint16_t timer_emu_time_ms;
  25. FuzzerWorkerUidChagedCallback tick_callback;
  26. void* tick_context;
  27. FuzzerWorkerEndCallback end_callback;
  28. void* end_context;
  29. };
  30. static bool fuzzer_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
  31. furi_assert(protocol_index < TOTAL_PROTOCOL_COUNT);
  32. instance->protocol = &fuzzer_proto_items[protocol_index];
  33. return hardware_worker_set_protocol_id_by_name(
  34. instance->hw_worker, fuzzer_proto_items[protocol_index].name);
  35. }
  36. // TODO make it protocol independent
  37. bool fuzzer_worker_load_key_from_file(
  38. FuzzerWorker* instance,
  39. FuzzerProtocolsID protocol_index,
  40. const char* filename) {
  41. furi_assert(instance);
  42. bool res = false;
  43. fuzzer_worker_set_protocol(instance, protocol_index); // TODO add Check
  44. if(!hardware_worker_load_key_from_file(instance->hw_worker, protocol_index, filename)) {
  45. } else {
  46. hardware_worker_get_protocol_data(
  47. instance->hw_worker, &instance->payload[0], MAX_PAYLOAD_SIZE);
  48. res = true;
  49. }
  50. return res;
  51. }
  52. static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) {
  53. furi_assert(instance);
  54. furi_assert(instance->protocol);
  55. bool res = false;
  56. const FuzzerProtocol* protocol = instance->protocol;
  57. switch(instance->attack_type) {
  58. case FuzzerWorkerAttackTypeDefaultDict:
  59. if(next) {
  60. if(instance->index < (protocol->dict.len - 1)) {
  61. instance->index++;
  62. } else {
  63. break;
  64. }
  65. }
  66. if(instance->index < protocol->dict.len) {
  67. memcpy(
  68. instance->payload,
  69. &protocol->dict.val[instance->index * protocol->data_size],
  70. protocol->data_size);
  71. res = true;
  72. }
  73. break;
  74. case FuzzerWorkerAttackTypeLoadFileCustomUids: {
  75. if(next) {
  76. instance->index++;
  77. }
  78. uint8_t str_len = protocol->data_size * 2 + 1;
  79. FuriString* data_str = furi_string_alloc();
  80. while(true) {
  81. furi_string_reset(data_str);
  82. if(!stream_read_line(instance->uids_stream, data_str)) {
  83. stream_rewind(instance->uids_stream);
  84. // TODO Check empty file & close stream and storage
  85. break;
  86. } else if(furi_string_get_char(data_str, 0) == '#') {
  87. // Skip comment string
  88. continue;
  89. } else if(furi_string_size(data_str) != str_len) {
  90. // Ignore strin with bad length
  91. FURI_LOG_W(TAG, "Bad string length");
  92. continue;
  93. } else {
  94. FURI_LOG_D(TAG, "Uid candidate: \"%s\"", furi_string_get_cstr(data_str));
  95. bool parse_ok = true;
  96. for(uint8_t i = 0; i < protocol->data_size; i++) {
  97. if(!hex_char_to_uint8(
  98. furi_string_get_cstr(data_str)[i * 2],
  99. furi_string_get_cstr(data_str)[i * 2 + 1],
  100. &instance->payload[i])) {
  101. parse_ok = false;
  102. break;
  103. }
  104. }
  105. res = parse_ok;
  106. }
  107. break;
  108. }
  109. }
  110. break;
  111. case FuzzerWorkerAttackTypeLoadFile:
  112. if(instance->payload[instance->index] != 0xFF) {
  113. instance->payload[instance->index]++;
  114. res = true;
  115. }
  116. break;
  117. default:
  118. break;
  119. }
  120. if(res) {
  121. hardware_worker_set_protocol_data(
  122. instance->hw_worker, &instance->payload[0], protocol->data_size);
  123. }
  124. return res;
  125. }
  126. static bool fuzzer_worker_load_previous_key(FuzzerWorker* instance) {
  127. furi_assert(instance);
  128. furi_assert(instance->protocol);
  129. bool res = false;
  130. const FuzzerProtocol* protocol = instance->protocol;
  131. switch(instance->attack_type) {
  132. case FuzzerWorkerAttackTypeDefaultDict:
  133. if(instance->index > 0) {
  134. instance->index--;
  135. memcpy(
  136. instance->payload,
  137. &protocol->dict.val[instance->index * protocol->data_size],
  138. protocol->data_size);
  139. res = true;
  140. }
  141. break;
  142. case FuzzerWorkerAttackTypeLoadFile:
  143. if(instance->payload[instance->index] != 0x00) {
  144. instance->payload[instance->index]--;
  145. res = true;
  146. }
  147. break;
  148. default:
  149. break;
  150. }
  151. if(res) {
  152. hardware_worker_set_protocol_data(
  153. instance->hw_worker, &instance->payload[0], protocol->data_size);
  154. }
  155. return res;
  156. }
  157. static void fuzzer_worker_on_tick_callback(void* context) {
  158. furi_assert(context);
  159. FuzzerWorker* instance = context;
  160. if(instance->in_emu_phase) {
  161. if(instance->treead_running) {
  162. hardware_worker_stop(instance->hw_worker);
  163. }
  164. instance->in_emu_phase = false;
  165. furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_idle_time_ms));
  166. } else {
  167. if(!fuzzer_worker_load_key(instance, true)) {
  168. fuzzer_worker_pause(instance); // XXX
  169. if(instance->end_callback) {
  170. instance->end_callback(instance->end_context);
  171. }
  172. } else {
  173. if(instance->treead_running) {
  174. hardware_worker_emulate_start(instance->hw_worker);
  175. }
  176. instance->in_emu_phase = true;
  177. furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
  178. if(instance->tick_callback) {
  179. instance->tick_callback(instance->tick_context);
  180. }
  181. }
  182. }
  183. }
  184. void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output_key) {
  185. furi_assert(instance);
  186. furi_assert(output_key);
  187. furi_assert(instance->protocol);
  188. output_key->data_size = instance->protocol->data_size;
  189. memcpy(output_key->data, instance->payload, instance->protocol->data_size);
  190. }
  191. bool fuzzer_worker_next_key(FuzzerWorker* instance) {
  192. furi_assert(instance);
  193. furi_assert(instance->protocol);
  194. return fuzzer_worker_load_key(instance, true);
  195. }
  196. bool fuzzer_worker_previous_key(FuzzerWorker* instance) {
  197. furi_assert(instance);
  198. furi_assert(instance->protocol);
  199. return fuzzer_worker_load_previous_key(instance);
  200. }
  201. bool fuzzer_worker_init_attack_dict(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
  202. furi_assert(instance);
  203. bool res = false;
  204. if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
  205. instance->attack_type = FuzzerWorkerAttackTypeMax;
  206. return res;
  207. }
  208. instance->attack_type = FuzzerWorkerAttackTypeDefaultDict;
  209. instance->index = 0;
  210. if(!fuzzer_worker_load_key(instance, false)) {
  211. instance->attack_type = FuzzerWorkerAttackTypeMax;
  212. } else {
  213. res = true;
  214. }
  215. return res;
  216. }
  217. bool fuzzer_worker_init_attack_file_dict(
  218. FuzzerWorker* instance,
  219. FuzzerProtocolsID protocol_index,
  220. FuriString* file_path) {
  221. furi_assert(instance);
  222. furi_assert(file_path);
  223. bool res = false;
  224. if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
  225. instance->attack_type = FuzzerWorkerAttackTypeMax;
  226. return res;
  227. }
  228. Storage* storage = furi_record_open(RECORD_STORAGE);
  229. instance->uids_stream = buffered_file_stream_alloc(storage);
  230. if(!buffered_file_stream_open(
  231. instance->uids_stream, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
  232. buffered_file_stream_close(instance->uids_stream);
  233. return res;
  234. }
  235. instance->attack_type = FuzzerWorkerAttackTypeLoadFileCustomUids;
  236. instance->index = 0;
  237. if(!fuzzer_worker_load_key(instance, false)) {
  238. instance->attack_type = FuzzerWorkerAttackTypeMax;
  239. buffered_file_stream_close(instance->uids_stream);
  240. furi_record_close(RECORD_STORAGE);
  241. } else {
  242. res = true;
  243. }
  244. return res;
  245. }
  246. bool fuzzer_worker_init_attack_bf_byte(
  247. FuzzerWorker* instance,
  248. FuzzerProtocolsID protocol_index,
  249. const FuzzerPayload* new_uid,
  250. uint8_t chusen) {
  251. furi_assert(instance);
  252. bool res = false;
  253. if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
  254. instance->attack_type = FuzzerWorkerAttackTypeMax;
  255. return res;
  256. }
  257. instance->attack_type = FuzzerWorkerAttackTypeLoadFile;
  258. instance->index = chusen;
  259. memcpy(instance->payload, new_uid->data, instance->protocol->data_size);
  260. res = true;
  261. return res;
  262. }
  263. FuzzerWorker* fuzzer_worker_alloc() {
  264. FuzzerWorker* instance = malloc(sizeof(FuzzerWorker));
  265. instance->hw_worker = hardware_worker_alloc();
  266. instance->suported_proto = malloc(sizeof(HwProtocolID) * TOTAL_PROTOCOL_COUNT);
  267. for(uint8_t i = 0; i < TOTAL_PROTOCOL_COUNT; i++) {
  268. if(!hardware_worker_set_protocol_id_by_name(
  269. instance->hw_worker, fuzzer_proto_items[i].name)) {
  270. // Check protocol support
  271. furi_crash("Not supported protocol name");
  272. } else {
  273. instance->suported_proto[i] = hardware_worker_get_protocol_id(instance->hw_worker);
  274. }
  275. }
  276. instance->attack_type = FuzzerWorkerAttackTypeMax;
  277. instance->index = 0;
  278. instance->treead_running = false;
  279. instance->in_emu_phase = false;
  280. memset(instance->payload, 0x00, sizeof(instance->payload));
  281. instance->timer_idle_time_ms = PROTOCOL_DEF_IDLE_TIME * 100;
  282. instance->timer_emu_time_ms = PROTOCOL_DEF_EMU_TIME * 100;
  283. instance->timer =
  284. furi_timer_alloc(fuzzer_worker_on_tick_callback, FuriTimerTypeOnce, instance);
  285. return instance;
  286. }
  287. void fuzzer_worker_free(FuzzerWorker* instance) {
  288. furi_assert(instance);
  289. fuzzer_worker_stop(instance);
  290. furi_timer_free(instance->timer);
  291. free(instance->suported_proto);
  292. hardware_worker_free(instance->hw_worker);
  293. free(instance);
  294. }
  295. bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_time) {
  296. furi_assert(instance);
  297. if(instance->attack_type < FuzzerWorkerAttackTypeMax) {
  298. if(idle_time == 0) {
  299. instance->timer_idle_time_ms = 10;
  300. } else {
  301. instance->timer_idle_time_ms = idle_time * 100;
  302. }
  303. if(emu_time == 0) {
  304. instance->timer_emu_time_ms = 10;
  305. } else {
  306. instance->timer_emu_time_ms = emu_time * 100;
  307. }
  308. FURI_LOG_D(
  309. TAG,
  310. "Emu_time %u ms Idle_time %u ms",
  311. instance->timer_emu_time_ms,
  312. instance->timer_idle_time_ms);
  313. if(!instance->treead_running) {
  314. hardware_worker_start_thread(instance->hw_worker);
  315. FURI_LOG_D(TAG, "Worker Starting");
  316. instance->treead_running = true;
  317. } else {
  318. FURI_LOG_D(TAG, "Worker UnPaused");
  319. }
  320. hardware_worker_emulate_start(instance->hw_worker);
  321. instance->in_emu_phase = true;
  322. furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
  323. return true;
  324. }
  325. return false;
  326. }
  327. void fuzzer_worker_start_emulate(FuzzerWorker* instance) {
  328. furi_assert(instance);
  329. if(!instance->treead_running) {
  330. hardware_worker_start_thread(instance->hw_worker);
  331. FURI_LOG_D(TAG, "Worker Starting");
  332. instance->treead_running = true;
  333. } else {
  334. FURI_LOG_D(TAG, "Worker UnPaused");
  335. }
  336. hardware_worker_emulate_start(instance->hw_worker);
  337. }
  338. void fuzzer_worker_pause(FuzzerWorker* instance) {
  339. furi_assert(instance);
  340. furi_timer_stop(instance->timer);
  341. if(instance->treead_running) {
  342. hardware_worker_stop(instance->hw_worker);
  343. FURI_LOG_D(TAG, "Worker Paused");
  344. }
  345. }
  346. void fuzzer_worker_stop(FuzzerWorker* instance) {
  347. furi_assert(instance);
  348. furi_timer_stop(instance->timer);
  349. if(instance->treead_running) {
  350. hardware_worker_stop_thread(instance->hw_worker);
  351. FURI_LOG_D(TAG, "Worker Stopping");
  352. instance->treead_running = false;
  353. }
  354. if(instance->attack_type == FuzzerWorkerAttackTypeLoadFileCustomUids) {
  355. buffered_file_stream_close(instance->uids_stream);
  356. furi_record_close(RECORD_STORAGE);
  357. instance->attack_type = FuzzerWorkerAttackTypeMax;
  358. }
  359. // TODO anything else
  360. }
  361. void fuzzer_worker_set_uid_chaged_callback(
  362. FuzzerWorker* instance,
  363. FuzzerWorkerUidChagedCallback callback,
  364. void* context) {
  365. furi_assert(instance);
  366. instance->tick_callback = callback;
  367. instance->tick_context = context;
  368. }
  369. void fuzzer_worker_set_end_callback(
  370. FuzzerWorker* instance,
  371. FuzzerWorkerEndCallback callback,
  372. void* context) {
  373. furi_assert(instance);
  374. instance->end_callback = callback;
  375. instance->end_context = context;
  376. }