From 8fd473ae080a46bd1196e195b1bcbdf1164dc0a4 Mon Sep 17 00:00:00 2001 From: JJTech Date: Sun, 3 Dec 2023 08:54:27 -0500 Subject: [PATCH] Create extractor.m --- extractor.m | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 extractor.m diff --git a/extractor.m b/extractor.m new file mode 100644 index 0000000..7fdb23e --- /dev/null +++ b/extractor.m @@ -0,0 +1,158 @@ +// Tool to extract IOKit data from a running machine and save it to a plist +// +// Usage: ./extractor + +#include +#include + +// Uses NSURL to get the root disk UUID +// Why were we using DiskArbitration anyway? +NSString *get_root_disk_uuid() { + NSURL *pathUrl = [NSURL fileURLWithPath:@"/"]; + NSString *volumeUUID = nil; + NSError *error = nil; + BOOL success = [pathUrl getResourceValue:&volumeUUID + forKey:NSURLVolumeUUIDStringKey + error:&error]; + + if (!success) { + NSLog(@"Error getting volume UUID: %@", error); + return nil; + } else { + return volumeUUID; + } +} + +// Gets the derived obfuscated iMessage keys from IOKit +// What are these for? +#define G_NAME "Gq3489ugfi" +#define F_NAME "Fyp98tpgj" +#define K_NAME "kbjfrfpoJU" +#define O_NAME "oycqAZloTNDm" +#define A_NAME "abKPld1EcMni" +NSDictionary *get_imessage_keys() { + io_service_t power_service = + IORegistryEntryFromPath(kIOMasterPortDefault, "IOPower:/"); + + return @{ + @G_NAME : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + power_service, CFSTR(G_NAME), kCFAllocatorDefault, 0), + @F_NAME : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + power_service, CFSTR(F_NAME), kCFAllocatorDefault, 0), + @K_NAME : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + power_service, CFSTR(K_NAME), kCFAllocatorDefault, 0), + @O_NAME : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + power_service, CFSTR(O_NAME), kCFAllocatorDefault, 0), + @A_NAME : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + power_service, CFSTR(A_NAME), kCFAllocatorDefault, 0), + }; +} + +// Gets the MAC address of the primary ethernet interface +// This might not work properly if you have multiple internal ethernet +// interfaces +NSData *get_mac_address() { + // Contruct a filter for IOEthernetInterface + CFMutableDictionaryRef filter = IOServiceMatching("IOEthernetInterface"); + // Add a key to the filter for IOPrimaryInterface = 1 + CFMutableDictionaryRef property_match = + CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(property_match, CFSTR("IOPrimaryInterface"), + kCFBooleanTrue); + CFDictionaryAddValue(filter, CFSTR("IOPropertyMatch"), property_match); + + // Get a list of ethernet services that match the filter + io_iterator_t ethernet_services_iter; + IOServiceGetMatchingServices(kIOMasterPortDefault, filter, + ðernet_services_iter); + // Get the first ethernet service + io_service_t ethernet_service = IOIteratorNext(ethernet_services_iter); + // Get the parent of the ethernet service + io_service_t ethernet_service_parent; + IORegistryEntryGetParentEntry(ethernet_service, kIOServicePlane, + ðernet_service_parent); + // Get the MAC address + return (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + ethernet_service_parent, CFSTR("IOMACAddress"), kCFAllocatorDefault, 0); +} + +// Gets the board id, product name, IOPlatformSerialNumber and IOPlatformUUID +// from IOKit +NSDictionary *get_device_info() { + io_service_t device_tree_service = + IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/"); + + return @{ + @"board-id" : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + device_tree_service, CFSTR("board-id"), kCFAllocatorDefault, 0), + @"product-name" : + (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + device_tree_service, CFSTR("product-name"), kCFAllocatorDefault, 0), + @"IOPlatformUUID" : + (__bridge_transfer NSString *)IORegistryEntryCreateCFProperty( + device_tree_service, CFSTR("IOPlatformUUID"), kCFAllocatorDefault, + 0), + @"IOPlatformSerialNumber" : + (__bridge_transfer NSString *)IORegistryEntryCreateCFProperty( + device_tree_service, CFSTR("IOPlatformSerialNumber"), + kCFAllocatorDefault, 0), + }; +} + +// Gets the MLB and ROM from IOKit using the special NVRAM keys +#define ROM_KEY "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ROM" +#define MLB_KEY "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:MLB" +NSDictionary *get_nvram_info() { + io_service_t options_service = + IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + + return @{ + @ROM_KEY : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + options_service, CFSTR(ROM_KEY), kCFAllocatorDefault, 0), + @MLB_KEY : (__bridge_transfer NSData *)IORegistryEntryCreateCFProperty( + options_service, CFSTR(MLB_KEY), kCFAllocatorDefault, 0), + }; +} + +int main(int argc, const char *argv[]) { + NSMutableDictionary *iokit_data = [[NSMutableDictionary alloc] init]; + + @try { + [iokit_data addEntriesFromDictionary:get_imessage_keys()]; + } @catch (NSException *exception) { + NSLog(@"Failed to get iMessage keys: %@", exception); + } + + @try { + [iokit_data addEntriesFromDictionary:get_device_info()]; + } @catch (NSException *exception) { + NSLog(@"Failed to get device info: %@", exception); + } + + @try { + [iokit_data addEntriesFromDictionary:get_nvram_info()]; + } @catch (NSException *exception) { + NSLog(@"Failed to get NVRAM info: %@", exception); + } + + @try { + [iokit_data setObject:get_mac_address() forKey:@"IOMACAddress"]; + } @catch (NSException *exception) { + NSLog(@"Failed to get MAC address: %@", exception); + } + + NSMutableDictionary *data = [[NSMutableDictionary alloc] init]; + + [data setObject:iokit_data forKey:@"iokit"]; + [data setObject:get_root_disk_uuid() forKey:@"root_disk_uuid"]; + + NSLog(@"data: %@", data); + + // Write the data to a plist + NSString *plist_path = @"data.plist"; + if (argc > 1) { + plist_path = [NSString stringWithUTF8String:argv[1]]; + } + [data writeToFile:plist_path atomically:YES]; +}