// // ALTPluginService.m // AltPlugin // // Created by Riley Testut on 11/14/19. // Copyright © 2019 Riley Testut. All rights reserved. // // OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network // // Copyright © 2021 Secure Mobile Networking Lab (SEEMOO) // Copyright © 2021 The Open Wireless Link Project // // SPDX-License-Identifier: AGPL-3.0-only // #import "OpenHaystackPluginService.h" #import #import "AppleAccountData.h" #import #import @import AppKit; @interface AKAppleIDSession : NSObject - (id)appleIDHeadersForRequest:(id)arg1; @end @interface AKDevice + (AKDevice *)currentDevice; - (NSString *)uniqueDeviceIdentifier; - (NSString *)serialNumber; - (NSString *)serverFriendlyDescription; @end @interface OpenHaystackPluginService () @property(nonatomic, readonly) NSISO8601DateFormatter *dateFormatter; @end @implementation OpenHaystackPluginService + (instancetype)sharedService { static OpenHaystackPluginService *_service = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _service = [[self alloc] init]; }); return _service; } - (instancetype)init { self = [super init]; if (self) { _dateFormatter = [[NSISO8601DateFormatter alloc] init]; } return self; } + (void)initialize { [[OpenHaystackPluginService sharedService] start]; } - (void)start { dlopen("/System/Library/PrivateFrameworks/AuthKit.framework/AuthKit", RTLD_NOW); [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"de.tu-darmstadt.seemoo.OpenHaystack.FetchAnisetteData" object:nil]; } - (void)receiveNotification:(NSNotification *)notification { NSString *requestUUID = notification.userInfo[@"requestUUID"]; NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"https://developerservices2.apple.com/services/QH65B2/listTeams.action?clientId=XABBG36SBA"]]; [req setHTTPMethod:@"POST"]; AKAppleIDSession *session = [[NSClassFromString(@"AKAppleIDSession") alloc] initWithIdentifier:@"com.apple.gs.xcode.auth"]; NSDictionary *headers = [session appleIDHeadersForRequest:req]; AKDevice *device = [NSClassFromString(@"AKDevice") currentDevice]; NSDate *date = [self.dateFormatter dateFromString:headers[@"X-Apple-I-Client-Time"]]; NSData *sptoken = [self fetchSearchpartyToken]; AppleAccountData *anisetteData = [[NSClassFromString(@"AppleAccountData") alloc] initWithMachineID:headers[@"X-Apple-I-MD-M"] oneTimePassword:headers[@"X-Apple-I-MD"] localUserID:headers[@"X-Apple-I-MD-LU"] routingInfo:[headers[@"X-Apple-I-MD-RINFO"] longLongValue] deviceUniqueIdentifier:device.uniqueDeviceIdentifier deviceSerialNumber:device.serialNumber deviceDescription:device.serverFriendlyDescription date:date locale:[NSLocale currentLocale] timeZone:[NSTimeZone localTimeZone]]; if (sptoken != nil) { anisetteData.searchPartyToken = [sptoken copy]; } NSData *data = [NSKeyedArchiver archivedDataWithRootObject:anisetteData requiringSecureCoding:YES error:nil]; [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"de.tu-darmstadt.seemoo.OpenHaystack.AnisetteDataResponse" object:nil userInfo:@{@"requestUUID" : requestUUID, @"anisetteData" : data} deliverImmediately:YES]; } - (NSData *_Nullable)fetchSearchpartyToken { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:@"com.apple.account.AppleAccount"]; NSArray *appleAccounts = [accountStore accountsWithAccountType:accountType]; if (appleAccounts == nil && appleAccounts.count > 0) { return nil; } ACAccount *iCloudAccount = appleAccounts[0]; ACAccountCredential *iCloudCredentials = iCloudAccount.credential; if ([iCloudCredentials respondsToSelector:NSSelectorFromString(@"credentialItems")]) { NSDictionary *credentialItems = [iCloudCredentials performSelector:NSSelectorFromString(@"credentialItems")]; NSString *searchPartyToken = credentialItems[@"search-party-token"]; NSData *tokenData = [searchPartyToken dataUsingEncoding:NSASCIIStringEncoding]; return tokenData; } return nil; } @end