mirror of
https://github.com/seemoo-lab/openhaystack.git
synced 2026-02-14 17:49:54 +00:00
137 lines
5.4 KiB
Objective-C
137 lines
5.4 KiB
Objective-C
//
|
||
// 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 <dlfcn.h>
|
||
|
||
#import "AppleAccountData.h"
|
||
#import <Accounts/Accounts.h>
|
||
#import <Security/Security.h>
|
||
|
||
@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
|