initial code for dumping imessages in a reasonable format

This commit is contained in:
Jeffrey Paul
2014-02-09 00:30:49 +01:00
parent c0021efb13
commit 9dd7628f04
157 changed files with 24178 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "AppleEffaceableStorage.h"
#include "IOKit.h"
int AppleEffaceableStorage__getLocker(uint32_t lockerId, uint8_t* buffer, size_t len) {
uint64_t outScalar = 0;
uint32_t one = 1;
uint64_t inScalar = lockerId;
return IOKit_call("AppleEffaceableStorage",
kAppleEffaceableStorageGetLocker,
&inScalar,
1,
NULL,
0,
&outScalar,
&one,
buffer,
&len);
}
int AppleEffaceableStorage__getBytes(uint8_t* buffer, size_t len)
{
const uint64_t offset = 0;
return IOKit_call("AppleEffaceableStorage",
kAppleEffaceableStorageGetBytes,
&offset,
1,
NULL,
0,
NULL,
NULL,
buffer,
&len);
}
int AppleEffaceableStorage__getLockerFromBytes(uint32_t tag, uint8_t* lockers, size_t lockers_len, uint8_t* buffer, size_t len)
{
struct EffaceableLocker* p = (struct EffaceableLocker*) lockers;
unsigned int i=0;
while (i < lockers_len)
{
//printf("p->magic=%x\n", p->magic);
if (p->magic != 'Lk') //0x4c6B
break;
if (p->len == 0 || ((i+8+p->len) > lockers_len))
break;
//printf("p->tag=%x\n", p->tag);
if ((p->tag & ~0x80000000) == tag)
{
len = len < p->len ? len : p->len;
memcpy(buffer, p->data, len);
return 0;
}
i = i + 8 + p->len;
p = (struct EffaceableLocker*) (&lockers[i]);
}
return -1;
}

View File

@@ -0,0 +1,40 @@
/*
AppleEffaceableStorage
0 : getCapacity
1 : getBytes (kernel debug)
2 : setBytes (kernel debug)
3 : isFormatted
4 : format
5 : getLocker
6 : setLocker
7 : effaceLocker
8 : lockerSpace
*/
#define kAppleEffaceableStorageGetBytes 1
#define kAppleEffaceableStorageGetLocker 5
#define LOCKER_DKEY 0x446B6579
#define LOCKER_EMF 0x454D4621
#define LOCKER_BAG1 0x42414731
#define LOCKER_LWVM 0x4C77564d
struct EffaceableLocker
{
unsigned short magic; //0x4c6B = "kL"
unsigned short len;
unsigned int tag; //BAG1, EMF, Dkey, DONE
unsigned char data[1];
};
struct BAG1Locker
{
unsigned int magic;//'BAG1';
unsigned char iv[16];
unsigned char key[32];
};
int AppleEffaceableStorage__getLocker(uint32_t lockerId, uint8_t* buffer, size_t len);
int AppleEffaceableStorage__getBytes(uint8_t* buffer, size_t len);
int AppleEffaceableStorage__getLockerFromBytes(uint32_t tag, uint8_t* lockers, size_t lockers_len, uint8_t* buffer, size_t len);

View File

@@ -0,0 +1,317 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonHMAC.h>
#include "IOKit.h"
#include "IOAESAccelerator.h"
#include "AppleEffaceableStorage.h"
#include "AppleKeyStore.h"
#include "util.h"
#include "bsdcrypto/rijndael.h"
#include "bsdcrypto/key_wrap.h"
CFDictionaryRef AppleKeyStore_loadKeyBag(const char* folder, const char* filename)
{
char keybagPath[100];
struct BAG1Locker bag1_locker={0};
//unsigned char buffer_bag1[52] = {0};
snprintf(keybagPath, 99, "%s/%s.kb", folder, filename);
CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(const UInt8*)keybagPath,
strlen(keybagPath),
0);
if (url == NULL)
return NULL;
CFReadStreamRef stream = CFReadStreamCreateWithFile (kCFAllocatorDefault, url);
if (stream == NULL)
return NULL;
if (CFReadStreamOpen(stream) != TRUE)
return NULL;
CFPropertyListRef plist = CFPropertyListCreateWithStream (kCFAllocatorDefault,
stream,
0,
kCFPropertyListImmutable,
NULL,
NULL
);
if (plist == NULL)
return NULL;
CFDataRef data = CFDictionaryGetValue(plist, CFSTR("_MKBPAYLOAD"));
if (data == NULL)
return NULL;
uint8_t* mkbpayload = valloc(CFDataGetLength(data));
CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), mkbpayload);
int length = CFDataGetLength(data);
if (length < 16)
{
free(mkbpayload);
return NULL;
}
if (AppleEffaceableStorage__getLocker(LOCKER_BAG1, (uint8_t*) &bag1_locker, sizeof(struct BAG1Locker)))
{
free(mkbpayload);
return NULL;
}
if (bag1_locker.magic != 'BAG1')
fprintf(stderr, "AppleKeyStore_loadKeyBag: bad BAG1 magic\n");
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
bag1_locker.key,
kCCKeySizeAES256,
bag1_locker.iv,
mkbpayload,
length,
mkbpayload,
length,
&decryptedSize);
if (cryptStatus != kCCSuccess)
{
fprintf(stderr, "AppleKeyStore_loadKeyBag CCCrypt kCCDecrypt with BAG1 key failed, return code=%x\n", cryptStatus);
free(mkbpayload);
return NULL;
}
CFDataRef data2 = CFDataCreate(kCFAllocatorDefault,
mkbpayload,
decryptedSize
);
if (data2 == NULL)
{
free(mkbpayload);
return NULL;
}
CFErrorRef e=NULL;
CFPropertyListRef plist2 = CFPropertyListCreateWithData(kCFAllocatorDefault, data2, kCFPropertyListImmutable, NULL, &e);
if (plist2 == NULL)
{
fprintf(stderr, "AppleKeyStore_loadKeyBag failed to create plist, AES fail ? decryptedSize=%zx\n", decryptedSize);
CFShow(e);
}
free(mkbpayload);
CFRelease(data2);
return plist2;
}
int AppleKeyStoreKeyBagInit()
{
uint64_t out = 0;
uint32_t one = 1;
return IOKit_call("AppleKeyStore",
kAppleKeyStoreInitUserClient,
NULL,
0,
NULL,
0,
&out,
&one,
NULL,
NULL);
}
int AppleKeyStoreKeyBagCreateWithData(CFDataRef data, uint64_t* keybagId)
{
uint32_t outCnt = 1;
aes_key_wrap_ctx ctx;
uint8_t hmckkey[32] = {0};
int retcode = IOKit_call("AppleKeyStore",
kAppleKeyStoreKeyBagCreateWithData,
NULL,
0,
CFDataGetBytePtr(data),
CFDataGetLength(data),
keybagId,
&outCnt,
NULL,
NULL
);
if (retcode != 0xE00002C9)
return retcode;
//HAX to load new iOS 7 keybags on previous iOS kernels
uint32_t* kbdata = (uint32_t*) CFDataGetBytePtr(data);
if ((kbdata[2] == 'SREV') && (kbdata[4] == 0x04000000))
{
printf("Patching iOS 7 keybag VERS 4 signature for older kernels\n");
aes_key_wrap_set_key(&ctx, IOAES_key835(), 16);
assert(kbdata[0x38/4] == 'KCMH');
assert(!aes_key_unwrap(&ctx, (const uint8_t*) &kbdata[0x38/4 + 2], hmckkey, 4));
assert(kbdata[CFSwapInt32BigToHost(kbdata[1])/4 + 2] == 'NGIS');
CCHmac(kCCHmacAlgSHA1,
(const void *) &kbdata[2],
CFSwapInt32BigToHost(kbdata[1]),
hmckkey,
32,
&kbdata[CFSwapInt32BigToHost(kbdata[1])/4 + 2 + 2]);
}
outCnt = 1;
return IOKit_call("AppleKeyStore",
kAppleKeyStoreKeyBagCreateWithData,
NULL,
0,
CFDataGetBytePtr(data),
CFDataGetLength(data),
keybagId,
&outCnt,
NULL,
NULL
);
}
int AppleKeyStoreKeyBagSetSystem(uint64_t keybagId)
{
return IOKit_call("AppleKeyStore",
kAppleKeyStoreKeyBagSetSystem,
&keybagId,
1,
NULL,
0,
NULL,
NULL,
NULL,
NULL);
}
int AppleKeyStoreUnlockDevice(io_connect_t conn, CFDataRef passcode)
{
return IOConnectCallMethod(conn,
kAppleKeyStoreUnlockDevice,
NULL,
0,
CFDataGetBytePtr(passcode),
CFDataGetLength(passcode),
NULL,
NULL,
NULL,
NULL);
}
KeyBag* AppleKeyStore_parseBinaryKeyBag(CFDataRef kb)
{
const uint8_t* ptr = CFDataGetBytePtr(kb);
unsigned int len = CFDataGetLength(kb);
struct KeyBagBlobItem* p = (struct KeyBagBlobItem*) ptr;
const uint8_t* end;
if (p->tag != 'ATAD') {
printf("Keybag does not start with DATA\n");
return NULL;
}
if (8 + CFSwapInt32BigToHost(p->len) > len) {
return NULL;
}
KeyBag* keybag = malloc(sizeof(KeyBag));
if (keybag == NULL)
return NULL;
memset(keybag, 0, sizeof(KeyBag));
end = ptr + 8 + CFSwapInt32BigToHost(p->len);
p = (struct KeyBagBlobItem*) p->data.bytes;
int kbuuid=0;
int i = -1;
while ((uint8_t*)p < end) {
//printf("%x\n", p->tag);
len = CFSwapInt32BigToHost(p->len);
if (p->tag == 'SREV') {
keybag->version = CFSwapInt32BigToHost(p->data.intvalue);
}
else if (p->tag == 'TLAS') {
memcpy(keybag->salt, p->data.bytes, 20);
}
else if (p->tag == 'RETI') {
keybag->iter = CFSwapInt32BigToHost(p->data.intvalue);
}
else if (p->tag == 'DIUU') {
if (!kbuuid)
{
memcpy(keybag->uuid, p->data.bytes, 16);
kbuuid = 1;
}
else
{
i++;
if (i >= MAX_CLASS_KEYS)
break;
memcpy(keybag->keys[i].uuid, p->data.bytes, 16);
}
}
else if (p->tag == 'SALC')
{
keybag->keys[i].clas = CFSwapInt32BigToHost(p->data.intvalue);
}
else if (p->tag == 'PARW' && kbuuid)
{
keybag->keys[i].wrap = CFSwapInt32BigToHost(p->data.intvalue);
}
else if (p->tag == 'YKPW')
{
memcpy(keybag->keys[i].wpky, p->data.bytes, (len > 40) ? 40 : len);
}
p = (struct KeyBagBlobItem*) &p->data.bytes[len];
}
keybag->numKeys = i + 1;
return keybag;
}
void AppleKeyStore_printKeyBag(KeyBag* kb)
{
int i;
printf("Keybag version : %d\n", kb->version);
printf("Keybag keys : %d\n", kb->numKeys);
printf("Class\tWrap\tKey\n");
for (i=0; i < kb->numKeys; i++)
{
printf("%d\t%d\t", kb->keys[i].clas, kb->keys[i].wrap);
printBytesToHex(kb->keys[i].wpky, kb->keys[i].wrap & 2 ? 40 : 32);
printf("\n");
}
printf("\n");
}
CFMutableDictionaryRef AppleKeyStore_getClassKeys(KeyBag* kb)
{
int i;
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, kb->numKeys, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef key;
for (i=0; i < kb->numKeys; i++)
{
if(kb->keys[i].wrap == 0)
{
key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), kb->keys[i].clas);
addHexaString(dict, key, kb->keys[i].wpky, 32);
CFRelease(key);
}
}
return dict;
}

View File

@@ -0,0 +1,83 @@
#include <IOKit/IOKitLib.h>
/*
AppleKeyStore
0 : initUserClient scalarOutSize=1
1 :
2 : AppleKeyStoreKeyBagCreate
3 : AppleKeyStoreKeyBagCopyData inscalars=id structOutSize=0x8000
4 : keybagrelease inscalars":[0]}
5 : AppleKeyStoreKeyBagSetSystem
6 : AppleKeyStoreKeyBagCreateWithData
7 : getlockstate "inscalars":[0], "scalarOutSize":1}
8 : AppleKeyStoreLockDevice
9 : AppleKeyStoreUnlockDevice instruct
10: AppleKeyStoreKeyWrap
11: AppleKeyStoreKeyUnwrap
12: AppleKeyStoreKeyBagUnlock
13: AppleKeyStoreKeyBagLock
14: AppleKeyStoreKeyBagGetSystem scalarOutSize=1
15: AppleKeyStoreKeyBagChangeSecret
17: AppleKeyStoreGetDeviceLockState scalarOutSize=1
18: AppleKeyStoreRecoverWithEscrowBag
19: AppleKeyStoreOblitClassD
*/
#define kAppleKeyStoreInitUserClient 0
#define kAppleKeyStoreKeyBagSetSystem 5
#define kAppleKeyStoreKeyBagCreateWithData 6
#define kAppleKeyStoreUnlockDevice 9
#define MAX_CLASS_KEYS 20
struct KeyBagBlobItem
{
unsigned int tag;
unsigned int len;
union
{
unsigned int intvalue;
unsigned char bytes[1];
} data;
};
typedef struct ClassKey
{
unsigned char uuid[16];
unsigned int clas;
unsigned int wrap;
unsigned char wpky[40];
} ClassKey;
typedef struct KeyBag
{
unsigned int version;
unsigned int type;
unsigned char uuid[16];
unsigned char hmck[40];
unsigned char salt[20];
unsigned int iter;
unsigned int numKeys;
struct ClassKey keys[MAX_CLASS_KEYS];
} KeyBag;
int AppleKeyStoreKeyBagInit();
CFDictionaryRef AppleKeyStore_loadKeyBag(const char* folder, const char* filename);
int AppleKeyStoreKeyBagCreateWithData(CFDataRef data, uint64_t* keybagId);
int AppleKeyStoreKeyBagSetSystem(uint64_t keybagId);
int AppleKeyStoreUnlockDevice(io_connect_t conn, CFDataRef passcode);
KeyBag* AppleKeyStore_parseBinaryKeyBag(CFDataRef kb);
void AppleKeyStore_printKeyBag(KeyBag* kb);
int AppleKeyStore_getPasscodeKey(KeyBag* keybag,
const char* passcode,
size_t passcodeLen,
uint8_t* passcodeKey);
int AppleKeyStore_unlockKeybagFromUserland(KeyBag* kb,
const char* passcode,
size_t passcodeLen,
uint8_t* key835);

View File

@@ -0,0 +1,145 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "IOKit.h"
#include "IOAESAccelerator.h"
#include "AppleEffaceableStorage.h"
#include "AppleKeyStore.h"
#include "bsdcrypto/pbkdf2.h"
#include "bsdcrypto/rijndael.h"
#include "bsdcrypto/key_wrap.h"
int AppleKeyStore_derivation(void* data, uint32_t dataLength, uint32_t iter, uint32_t vers);
uint32_t AppleKeyStore_xorExpand(uint32_t* dst, uint32_t dstLen, uint32_t* input, uint32_t inLen, uint32_t xorKey);
void AppleKeyStore_xorCompress(uint32_t* input, uint32_t inputLen, uint32_t* output, uint32_t outputLen);
#define DERIVATION_BUFFER_SIZE 4096
uint8_t buf1[DERIVATION_BUFFER_SIZE];
uint8_t buf2[DERIVATION_BUFFER_SIZE];
IOByteCount IOAESStructSize1 = sizeof(IOAESStruct);
IOAESStruct in ={buf1,buf2,DERIVATION_BUFFER_SIZE,{0},0,128,{0},kIOAESAcceleratorUIDMask,0};
IOAESStruct out = {0};
int AppleKeyStore_getPasscodeKey(KeyBag* keybag,
const char* passcode,
size_t passcodeLen,
uint8_t* passcodeKey)
{
//One PBKDF2 iter, hardcoded salt length
pkcs5_pbkdf2(passcode, passcodeLen, keybag->salt, 20, passcodeKey, 32, 1);
return AppleKeyStore_derivation(passcodeKey, 32, keybag->iter, keybag->version);
}
int AppleKeyStore_derivation(void* data, uint32_t dataLength, uint32_t iter, uint32_t vers)
{
IOReturn ret;
io_connect_t conn = IOAESAccelerator_getIOconnect();
memset(in.iv, 0, 16);
uint32_t r4;
uint32_t nBlocks = DERIVATION_BUFFER_SIZE / dataLength; //4096/32=128
uint32_t xorkey = 1;
uint32_t* buffer2 = data;
if (vers >= 2)
{
buffer2 = malloc(dataLength);
memcpy(buffer2, data, dataLength);
}
while (iter > 0)
{
//version=1 xorKey alawys=1, buffer2 changes at each iter
//version=2 xorKey changes at each iter, buffer2 is always the input (pbkdf2(passcode))
r4 = AppleKeyStore_xorExpand((uint32_t*)buf1, DERIVATION_BUFFER_SIZE, buffer2, dataLength, xorkey);
if (vers >= 2)
xorkey = r4;
if((ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize1, &out, &IOAESStructSize1)) != kIOReturnSuccess)
{
fprintf(stderr, "IOConnectCallStructMethod fail : %x\n", ret);
return -1;
}
memcpy(in.iv, out.iv, 16);
r4 = nBlocks;
if (r4 >= iter)
{
r4 = iter;
}
AppleKeyStore_xorCompress((uint32_t*) buf2, r4 * dataLength, data, dataLength);
iter -= r4;
}
if (vers >= 2)
{
free(buffer2);
}
return 0;
}
/*
uint32_t paddedLen = (inLen + 3) & (~3);//aligne sur 4 octets
if (dstLen % paddedLen)
return;
uint32_t localBuf[inLen/4];
memcpy(localBuf, input, inLen);
memset(&localBuf[inLen], 0, paddedLen - inLen);*/
uint32_t AppleKeyStore_xorExpand(uint32_t* dst, uint32_t dstLen, uint32_t* input, uint32_t inLen, uint32_t xorKey)
{
uint32_t* dstEnd = &dst[dstLen/4];
uint32_t i = 0;
while (dst < dstEnd)
{
i = 0;
while (i < inLen/4)
{
*dst = input[i] ^ xorKey;
dst++;
i++;
}
xorKey++;
}
return xorKey;
}
void AppleKeyStore_xorCompress(uint32_t* input, uint32_t inputLen, uint32_t* output, uint32_t outputLen)
{
uint32_t i;
for (i=0; i < (inputLen/4); i++)
{
output[i%(outputLen/4)] ^= input[i];
}
}
int AppleKeyStore_unlockKeybagFromUserland(KeyBag* kb, const char* passcode, size_t passcodeLen, uint8_t* key835)
{
u_int8_t passcodeKey[32]={0};
u_int8_t unwrappedKey[40]={0};
aes_key_wrap_ctx ctx;
int i;
AppleKeyStore_getPasscodeKey(kb, passcode, passcodeLen, passcodeKey);
aes_key_wrap_set_key(&ctx, passcodeKey, 32);
for (i=0; i < kb->numKeys; i++)
{
if (kb->keys[i].wrap & 2)
{
if(aes_key_unwrap(&ctx, kb->keys[i].wpky, unwrappedKey, 4))
return 0;
memcpy(kb->keys[i].wpky, unwrappedKey, 32);
kb->keys[i].wrap &= ~2;
}
if (kb->keys[i].wrap & 1)
{
doAES(kb->keys[i].wpky, kb->keys[i].wpky, 32, kIOAESAcceleratorCustomMask, key835, NULL, kIOAESAcceleratorDecrypt, 128);
kb->keys[i].wrap &= ~1;
}
}
return 1;
}

View File

@@ -0,0 +1,160 @@
/**
https://github.com/planetbeing/xpwn/blob/master/crypto/aes.c
**/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <IOKit/IOKitLib.h>
#include <pthread.h>
#include "IOAESAccelerator.h"
#include "IOKit.h"
io_connect_t conn = 0;
IOByteCount IOAESStructSize = sizeof(IOAESStruct);
pthread_once_t once_control = PTHREAD_ONCE_INIT;
//see com.apple.driver.AppleCDMA
typedef struct
{
uint32_t key_id;
uint32_t hw_key_id;
uint8_t nonce_to_encrypt_with_hw_key[16];
uint8_t* value;
} device_key_descriptor;
#define NUM_DEVICE_KEYS 4
device_key_descriptor ios_device_keys[NUM_DEVICE_KEYS]= {
{0x835, kIOAESAcceleratorUIDMask, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, NULL},
{0x899, kIOAESAcceleratorUIDMask, {0xD1, 0xE8, 0xFC, 0xB5, 0x39, 0x37, 0xBF, 0x8D, 0xEF, 0xC7, 0x4C, 0xD1, 0xD0, 0xF1, 0xD4, 0xB0}, NULL},
{0x89B, kIOAESAcceleratorUIDMask, {0x18, 0x3E, 0x99, 0x67, 0x6B, 0xB0, 0x3C, 0x54, 0x6F, 0xA4, 0x68, 0xF5, 0x1C, 0x0C, 0xBD, 0x49}, NULL},
{0x89A, kIOAESAcceleratorUIDMask, {0xDB, 0x1F, 0x5B, 0x33, 0x60, 0x6C, 0x5F, 0x1C, 0x19, 0x34, 0xAA, 0x66, 0x58, 0x9C, 0x06, 0x61}, NULL},
};
void aes_init()
{
conn = IOKit_getConnect("IOAESAccelerator");
}
io_connect_t IOAESAccelerator_getIOconnect()
{
pthread_once(&once_control, aes_init);
return conn;
}
int doAES(void* inbuf, void *outbuf, uint32_t size, uint32_t keyMask, void* key, void* iv, int mode, int bits) {
IOReturn ret;
IOAESStruct in;
pthread_once(&once_control, aes_init);
in.mode = mode;
in.bits = bits;
in.inbuf = inbuf;
in.outbuf = outbuf;
in.size = size;
in.mask = keyMask;
memset(in.keybuf, 0, sizeof(in.keybuf));
if(key)
memcpy(in.keybuf, key, in.bits / 8);
if(iv)
memcpy(in.iv, iv, 16);
else
memset(in.iv, 0, 16);
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
if(ret == kIOReturnBadArgument) {
IOAESStructSize = IOAESStruct_sizeold;
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
}
if(iv)
memcpy(iv, in.iv, 16);
return ret;
}
IOReturn doAES_wrapper(void* thisxxx, int mode, void* iv, void* outbuf, void *inbuf, uint32_t size, uint32_t keyMask)
{
int x = doAES(inbuf, outbuf, size, keyMask, NULL, iv, mode, 128);
return !x;
}
int patch_IOAESAccelerator();
int AES_UID_Encrypt(void* input2, void* output, size_t len)
{
IOAESStruct in;
IOReturn ret;
static int triedToPatchKernelAlready = 0;
unsigned char* input = valloc(16);
memcpy(input, input2, 16);
pthread_once(&once_control, aes_init);
in.mode = kIOAESAcceleratorEncrypt;
in.mask = kIOAESAcceleratorUIDMask;
in.bits = 128;
in.inbuf = input;
in.outbuf = output;
in.size = len;
memset(in.keybuf, 0, sizeof(in.keybuf));
memset(in.iv, 0, 16);
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
if(ret == kIOReturnBadArgument) {
IOAESStructSize = IOAESStruct_sizeold;
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
}
if(ret == kIOReturnNotPrivileged && !triedToPatchKernelAlready) {
triedToPatchKernelAlready = 1;
fprintf(stderr, "Trying to patch IOAESAccelerator kernel extension to allow UID key usage\n");
patch_IOAESAccelerator();
ret = AES_UID_Encrypt(input2, output, len);
}
if(ret != kIOReturnSuccess) {
fprintf(stderr, "IOAESAccelerator returned: %x\n", ret);
}
return ret;
}
uint8_t* IOAES_get_device_key(uint32_t id)
{
static uint8_t nullkey[16] = {0};
int i;
for(i=0; i < NUM_DEVICE_KEYS; i++)
{
if (ios_device_keys[i].key_id != id)
continue;
if (ios_device_keys[i].value != NULL)
return ios_device_keys[i].value;
ios_device_keys[i].value = (uint8_t*) valloc(16); //on ARMv6 devices stuff needs to be aligned
memcpy(ios_device_keys[i].value, ios_device_keys[i].nonce_to_encrypt_with_hw_key, 16);
AES_UID_Encrypt(ios_device_keys[i].value, ios_device_keys[i].value, 16);
return ios_device_keys[i].value;
}
return nullkey;
}
uint8_t* IOAES_key835()
{
return IOAES_get_device_key(0x835);
}
uint8_t* IOAES_key89B()
{
return IOAES_get_device_key(0x89B);
}
uint8_t* IOAES_key89A()
{
return IOAES_get_device_key(0x89A);
}

View File

@@ -0,0 +1,36 @@
#define kIOAESAcceleratorInfo 0
#define kIOAESAcceleratorTask 1
#define kIOAESAcceleratorTest 2
#define kIOAESAcceleratorEncrypt 0
#define kIOAESAcceleratorDecrypt 1
#define kIOAESAcceleratorGIDMask 0x3E8
#define kIOAESAcceleratorUIDMask 0x7D0
#define kIOAESAcceleratorCustomMask 0
typedef struct
{
void* inbuf;
void* outbuf;
uint32_t size;
uint8_t iv[16];
uint32_t mode;
uint32_t bits;
uint8_t keybuf[32];
uint32_t mask;
uint32_t zero; //ios 4.2.1
} IOAESStruct;
#define IOAESStruct_size41 (sizeof(IOAESStruct))
#define IOAESStruct_sizeold (sizeof(IOAESStruct) - 4)
void aes_init();
io_connect_t IOAESAccelerator_getIOconnect();
int doAES(void* inbuf, void *outbuf, uint32_t size, uint32_t keyMask, void* key, void* iv, int mode, int bits);
int AES_UID_Encrypt(void* input, void* output, size_t len);
uint8_t* IOAES_key835();
uint8_t* IOAES_key89A();
uint8_t* IOAES_key89B();

View File

@@ -0,0 +1,90 @@
#include <stdio.h>
#include <string.h>
#include "IOKit.h"
struct ioconnectCache {
const char* serviceName;
io_connect_t conn;
};
struct ioconnectCache cache[10]={{NULL, 0}};
void __attribute__((destructor)) IOKit_destruct()
{
int i;
for (i=0; i < 10 && cache[i].conn != 0; i++) {
//printf("Closing %s\n", cache[i].serviceName);
IOServiceClose(cache[i].conn);
}
}
io_connect_t IOKit_getConnect(const char* serviceName)
{
IOReturn ret;
io_connect_t conn = 0;
int i;
for (i=0; i < 10 && cache[i].serviceName != NULL; i++) {
if (!strcmp(serviceName, cache[i].serviceName))
{
//printf("got cache for %s\n", serviceName);
return cache[i].conn;
}
}
CFMutableDictionaryRef dict = IOServiceMatching(serviceName);
io_service_t dev = IOServiceGetMatchingService(kIOMasterPortDefault, dict);
if(!dev) {
fprintf(stderr, "FAIL: Could not get %s service\n", serviceName);
return -1;
}
ret = IOServiceOpen(dev, mach_task_self(), 0, &conn);
IOObjectRelease(dev);
if(ret != kIOReturnSuccess) {
fprintf(stderr, "FAIL: Cannot open service %s\n", serviceName);
return -1;
}
if (i < 10) {
cache[i].serviceName = serviceName;
cache[i].conn = conn;
}
return conn;
}
IOReturn IOKit_call(const char* serviceName,
uint32_t selector,
const uint64_t *input,
uint32_t inputCnt,
const void *inputStruct,
size_t inputStructCnt,
uint64_t *output,
uint32_t *outputCnt,
void *outputStruct,
size_t *outputStructCnt)
{
IOReturn ret;
io_connect_t conn = IOKit_getConnect(serviceName);
ret = IOConnectCallMethod(conn,
selector,
input,
inputCnt,
inputStruct,
inputStructCnt,
output,
outputCnt,
outputStruct,
outputStructCnt);
if (ret != kIOReturnSuccess)
{
fprintf(stderr, "IOConnectCallMethod on %s selector %d returned %x\n", serviceName, selector, ret);
}
return ret;
}

View File

@@ -0,0 +1,14 @@
#include <IOKit/IOKitLib.h>
io_connect_t IOKit_getConnect(const char* serviceName);
IOReturn IOKit_call(const char* serviceName,
uint32_t selector,
const uint64_t *input,
uint32_t inputCnt,
const void *inputStruct,
size_t inputStructCnt,
uint64_t *output,
uint32_t *outputCnt,
void *outputStruct,
size_t *outputStructCnt);

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* IOUSBDeviceControllerLib.h
* IOUSBDeviceFamily
*
* Created by Paul Chinn on 11/6/07.
* Copyright 2007 Apple Inc. All rights reserved.
*
*/
#ifndef _IOKIT_IOUSBDEVICECONTROLLERLIB_H_
#define _IOKIT_IOUSBDEVICECONTROLLERLIB_H_
#include <IOKit/IOTypes.h>
#include <IOKit/IOReturn.h>
#include <CoreFoundation/CoreFoundation.h>
/*!
@header IOUSBDeviceControllerLib
IOUSBDeviceControllerLib provides some API to access devicce-mode-usb controllers.
*/
__BEGIN_DECLS
/*! @typedef IOUSBDeviceControllerRef
@abstract This is the type of a reference to the IOUSBDeviceController.
*/
typedef struct __IOUSBDeviceController* IOUSBDeviceControllerRef;
/*! @typedef IOUSBDeviceDescriptionRef
@abstract Object that describes the device, configurations and interfaces of a IOUSBDeviceController.
*/
typedef struct __IOUSBDeviceDescription* IOUSBDeviceDescriptionRef;
/*! @typedef IOUSBDeviceArrivalCallback
@abstract Function callback for notification of asynchronous arrival of an IOUSBDeviceController .
*/
typedef void (*IOUSBDeviceArrivalCallback) (
void * context,
IOUSBDeviceControllerRef device);
/*!
@function IOUSBDeviceControllerGetTypeID
@abstract Returns the type identifier of all IOUSBDeviceController instances.
*/
CF_EXPORT
CFTypeID IOUSBDeviceControllerGetTypeID(void)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*!
@function IOUSBDeviceDescriptionGetTypeID
@abstract Returns the type identifier of all IOUSBDeviceDescription instances.
*/
CF_EXPORT
CFTypeID IOUSBDeviceDescriptionGetTypeID(void)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*!
@function IOUSBDeviceControllerCreate
@abstract Creates an IOUSBDeviceController object.
@discussion Creates a CF object that provides access to the kernel's IOUSBDeviceController IOKit object.
@param allocator Allocator to be used during creation.
@param deviceRef The newly created object. Only valid if the call succeeds.
@result The status of the call. The call will fail if no IOUSBDeviceController exists in the kernel.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerCreate(
CFAllocatorRef allocator,
IOUSBDeviceControllerRef* deviceRef
)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*!
@function IOUSBDeviceControllerGoOffAndOnBus
@abstract Cause the controller to drop off bus and return.
@discussion The controller will drop off USB appearing to the host as if it has been unlugged. After the given msecDelay
has elapsed, it will come back on bus.
@param deviceRef The controller object
@param msecDelay The time in milliseconds to stay off-bus.
@result The status of the call.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerGoOffAndOnBus(IOUSBDeviceControllerRef device, uint32_t msecDelay)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*!
@function IOUSBDeviceControllerForceOffBus
@abstract Cause the controller to stay off.
@discussion The controller will drop off USB appearing to the host as if it has been unlugged.
@param deviceRef The controller object
@param enable If true the controller is dropped off the bus and kept off. When false the controller will no longer be forced off.
@result The status of the call.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerForceOffBus(IOUSBDeviceControllerRef device, int enable)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceControllerRegisterArrivalCallback
@abstract Schedules async controller arrival with a run loop
@discussion Establishs a callback to be invoked when an IOUSBDeviceController becomes available in-kernel.
@param callback The function invoked when the controller arrives. It receives a IOUSBDeviceControllerRef annd the caller-provided context.
@param context A caller-specified pointer that is provided when the callback is invoked.
@param runLoop RunLoop to be used when scheduling any asynchronous activity.
@param runLoopMode Run loop mode to be used when scheduling any asynchronous activity.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerRegisterArrivalCallback(IOUSBDeviceArrivalCallback callback, void *context, CFRunLoopRef runLoop, CFStringRef runLoopMode)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceControllerRemoveArrivalCallback()
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceControllerSetDescription
@abstract Provide the information required to configure the IOUSBDeviceController in kernel
@param device The controller instance to receive the description
@param description The description to use.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerSetDescription(IOUSBDeviceControllerRef device, IOUSBDeviceDescriptionRef description)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceControllerSendCommand
@abstract Issue a command to the in-kernel usb-device stack
@discussion This sends a command string and optional parameter object into the kernel. Commands are passed to the controller-driver, the
"device", then to the individual interface drivers, until one of those handles it.
@param device The controller instance to receive the command
@param command A string command. Valid commands are determined by the various in-kernel drivers comprising the usb-device stack
@param param An optional, arbitrary object that is appropriate for the given command
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerSendCommand(IOUSBDeviceControllerRef device, CFStringRef command, CFTypeRef param)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceControllerSetPreferredConfiguration
@abstract Sets the preferred configuration number to gain desired functionality on the host
@param device The controller instance to receive the description
@param config Preferred configuration number that will be sent to the host.
*/
CF_EXPORT
IOReturn IOUSBDeviceControllerSetPreferredConfiguration(IOUSBDeviceControllerRef device, int config)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
IOUSBDeviceDescriptionRef IOUSBDeviceDescriptionCreate(CFAllocatorRef allocator)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceDescriptionCreateFromController
@abstract Retrieve the current description from the IOUSBDeviceController
@discussion This retrieves the currently set description from the kernel's IOUSBDeviceController. It represents the full description of the device as
it is currently presented on the USB. The call can fail if the controller exists but has not et received a description.
@param allocator The CF allocator to use when creating the description
@param device The controller instance from which to receive the description
*/
CF_EXPORT
IOUSBDeviceDescriptionRef IOUSBDeviceDescriptionCreateFromController(CFAllocatorRef allocator, IOUSBDeviceControllerRef)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
/*! @function IOUSBDeviceDescriptionCreateFromDefaults
@abstract Create a descripion based on the hardwares default usb description.
@discussion This retrieves the default description for the device. It describes the main usb functionality provided by the device and is what is used for
a normal system. Currently the description is retrieved from a plist on disk and is keyed to a sysctl that describes the hardware.
@param allocator The CF allocator to use when creating the description
*/
CF_EXPORT
IOUSBDeviceDescriptionRef IOUSBDeviceDescriptionCreateFromDefaults(CFAllocatorRef allocator)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
IOUSBDeviceDescriptionRef IOUSBDeviceDescriptionCreate(CFAllocatorRef allocator)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint8_t IOUSBDeviceDescriptionGetClass(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceDescriptionSetClass(IOUSBDeviceDescriptionRef ref, UInt8 bClass)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint8_t IOUSBDeviceDescriptionGetSubClass(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint8_t IOUSBDeviceDescriptionGetProtocol(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint16_t IOUSBDeviceDescriptionGetVendorID(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceDescriptionSetVendorID(IOUSBDeviceDescriptionRef devDesc, UInt16 vendorID)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint16_t IOUSBDeviceDescriptionGetProductID(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceDescriptionSetProductID(IOUSBDeviceDescriptionRef devDesc, UInt16 productID)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
uint16_t IOUSBDeviceDescriptionGetVersion(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
CFStringRef IOUSBDeviceDescriptionGetManufacturerString(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
CFStringRef IOUSBDeviceDescriptionGetProductString(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
CFStringRef IOUSBDeviceDescriptionGetSerialString(IOUSBDeviceDescriptionRef ref)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceDescriptionSetSerialString(IOUSBDeviceDescriptionRef ref, CFStringRef serial)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
int IOUSBDeviceDescriptionAppendInterfaceToConfiguration(IOUSBDeviceDescriptionRef devDesc, int config, CFStringRef name);
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
int IOUSBDeviceDescriptionAppendConfiguration(IOUSBDeviceDescriptionRef devDesc, CFStringRef textDescription, UInt8 attributes, UInt8 maxPower);
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
void IOUSBDeviceDescriptionRemoveAllConfigurations(IOUSBDeviceDescriptionRef devDesc)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
io_service_t IOUSBDeviceControllerGetService(IOUSBDeviceControllerRef controller);
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
CF_EXPORT
int IOUSBDeviceDescriptionGetMatchingConfiguration(IOUSBDeviceDescriptionRef devDesc, CFArrayRef interfaceNames);
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
__END_DECLS
#endif

View File

@@ -0,0 +1,51 @@
SDKVER?=5.1
ARCH?=armv7
MINIOS=4.0
SDK=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(SDKVER).sdk/
HGVERSION:= $(shell hg parents --template '{node|short}' || echo "unknown")
CC=clang -arch $(ARCH)
CFLAGS=-Wall -isysroot $(SDK) -DHGVERSION="\"${HGVERSION}\"" -O3 -I.
CFLAGS+= -framework CoreFoundation -framework IOKit -framework Security
CFLAGS+= -miphoneos-version-min=$(MINIOS)
CODESIGN=codesign -s - --entitlements
all: $(SDK) IOKit IOUSBDeviceControllerLib.h device_infos restored_external bruteforce ioflashstoragekit
$(SDK):
@echo "iOS SDK not found in $(SDK)"
@echo "=> check SDKVER/SDK in Makefile"
IOUSBDeviceControllerLib.h:
curl -o IOUSBDeviceControllerLib.h http://www.opensource.apple.com/source/IOKitUser/IOKitUser-502/usb_device.subproj/IOUSBDeviceControllerLib.h?txt
IOKit:
ln -s /System/Library/Frameworks/IOKit.framework/Versions/Current/Headers IOKit
device_infos: device_infos.c device_info.c IOAESAccelerator.c AppleEffaceableStorage.c AppleKeyStore.c bsdcrypto/pbkdf2.c bsdcrypto/sha1.c bsdcrypto/key_wrap.c bsdcrypto/rijndael.c util.c IOKit.c registry.c ioflash/ioflash.c kernel_patcher.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) tfp0.plist $@
restored_external: restored_external.c device_info.c remote_functions.c plist_server.c AppleKeyStore.c AppleEffaceableStorage.c IOKit.c IOAESAccelerator.c util.c registry.c AppleKeyStore_kdf.c bsdcrypto/pbkdf2.c bsdcrypto/sha1.c bsdcrypto/rijndael.c bsdcrypto/key_wrap.c ioflash/ioflash.c kernel_patcher.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) keystore_device.xml $@
bruteforce: systemkb_bruteforce.c AppleKeyStore.c AppleEffaceableStorage.c IOKit.c IOAESAccelerator.c util.c registry.c AppleKeyStore_kdf.c bsdcrypto/pbkdf2.c bsdcrypto/sha1.c bsdcrypto/rijndael.c bsdcrypto/key_wrap.c device_info.c ioflash/ioflash.c kernel_patcher.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) keystore_device.xml $@
ioflashstoragekit: ioflash/ioflash.c ioflash/ioflash_kernel.c ioflash/ioflashstoragekit.c util.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) tfp0.plist $@
kernel_patcher: kernel_patcher.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) tfp0.plist $@
shsh_dump: ioflash/ioflash.c ioflash/ioflash_kernel.c shsh_dump.c util.c
$(CC) $(CFLAGS) -o $@ $^
$(CODESIGN) tfp0.plist $@
clean:
rm -f bruteforce restored_external device_infos ioflashstoragekit shsh_dump
rebuild: clean all

View File

@@ -0,0 +1,119 @@
/* $OpenBSD: key_wrap.c,v 1.3 2011/01/11 15:42:05 deraadt Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This code implements the AES Key Wrap algorithm described in RFC 3394.
*/
#include <sys/param.h>
#include <string.h>
//haxs to compile on osx
#include <CoreFoundation/CoreFoundation.h>
#define timingsafe_bcmp bcmp
#define ovbcopy bcopy
#define explicit_bzero bzero
#define htobe64 CFSwapInt64BigToHost
#include "rijndael.h"
#include "key_wrap.h"
static const u_int8_t IV[8] =
{ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
void
aes_key_wrap_set_key(aes_key_wrap_ctx *ctx, const u_int8_t *K, size_t K_len)
{
rijndael_set_key(&ctx->ctx, K, K_len * NBBY);
}
void
aes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *ctx, const u_int8_t *K,
size_t K_len)
{
rijndael_set_key_enc_only(&ctx->ctx, K, K_len * NBBY);
}
void
aes_key_wrap(aes_key_wrap_ctx *ctx, const u_int8_t *P, size_t n, u_int8_t *C)
{
u_int64_t B[2], t;
u_int8_t *A, *R;
size_t i;
int j;
ovbcopy(P, C + 8, n * 8); /* P and C may overlap */
A = C; /* A points to C[0] */
memcpy(A, IV, 8); /* A = IV, an initial value */
for (j = 0, t = 1; j <= 5; j++) {
R = C + 8;
for (i = 1; i <= n; i++, t++) {
/* B = A | R[i] */
memcpy(&B[0], A, 8);
memcpy(&B[1], R, 8);
/* B = AES(K, B) */
rijndael_encrypt(&ctx->ctx, (caddr_t)B, (caddr_t)B);
/* MSB(64, B) = MSB(64, B) ^ t */
B[0] ^= htobe64(t);
/* A = MSB(64, B) */
memcpy(A, &B[0], 8);
/* R[i] = LSB(64, B) */
memcpy(R, &B[1], 8);
R += 8;
}
}
explicit_bzero(B, sizeof B);
}
int
aes_key_unwrap(aes_key_wrap_ctx *ctx, const u_int8_t *C, u_int8_t *P, size_t n)
{
u_int64_t B[2], t;
u_int8_t A[8], *R;
size_t i;
int j;
memcpy(A, C, 8); /* A = C[0] */
ovbcopy(C + 8, P, n * 8); /* P and C may overlap */
for (j = 5, t = 6 * n; j >= 0; j--) {
R = P + (n - 1) * 8;
for (i = n; i >= 1; i--, t--) {
/* MSB(64, B) = A */
memcpy(&B[0], A, 8);
/* MSB(64, B) = MSB(64, B) ^ t */
B[0] ^= htobe64(t);
/* B = MSB(64, B) | R[i] */
memcpy(&B[1], R, 8);
/* B = AES-1(K, B) */
rijndael_decrypt(&ctx->ctx, (caddr_t)B, (caddr_t)B);
/* A = MSB(64, B) */
memcpy(A, &B[0], 8);
/* R[i] = LSB(64, B) */
memcpy(R, &B[1], 8);
R -= 8;
}
}
explicit_bzero(B, sizeof B);
/* check that A is an appropriate initial value */
return timingsafe_bcmp(A, IV, 8) != 0;
}

View File

@@ -0,0 +1,40 @@
/* $OpenBSD: key_wrap.h,v 1.1 2008/08/12 15:43:00 damien Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _KEY_WRAP_H_
#define _KEY_WRAP_H_
typedef unsigned char u_int8_t;
typedef struct _aes_key_wrap_ctx {
rijndael_ctx ctx;
} aes_key_wrap_ctx;
#include <sys/cdefs.h>
__BEGIN_DECLS
void aes_key_wrap_set_key(aes_key_wrap_ctx *, const u_int8_t *, size_t);
void aes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *, const u_int8_t *,
size_t);
void aes_key_wrap(aes_key_wrap_ctx *, const u_int8_t *, size_t, u_int8_t *);
int aes_key_unwrap(aes_key_wrap_ctx *, const u_int8_t *, u_int8_t *,
size_t);
__END_DECLS
#endif /* _KEY_WRAP_H_ */

View File

@@ -0,0 +1,253 @@
/* $OpenBSD: pbkdf2.c,v 1.1 2008/06/14 06:28:27 djm Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include "sha1.h"
#include "pbkdf2.h"
/* #define PBKDF2_MAIN */
/*
* HMAC-SHA-1 (from RFC 2202).
*/
static void
hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
{
SHA1_CTX ctx;
u_int8_t k_pad[SHA1_BLOCK_LENGTH];
u_int8_t tk[SHA1_DIGEST_LENGTH];
int i;
if (key_len > SHA1_BLOCK_LENGTH) {
SHA1Init(&ctx);
SHA1Update(&ctx, key, key_len);
SHA1Final(tk, &ctx);
key = tk;
key_len = SHA1_DIGEST_LENGTH;
}
bzero(k_pad, sizeof k_pad);
bcopy(key, k_pad, key_len);
for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
k_pad[i] ^= 0x36;
SHA1Init(&ctx);
SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
SHA1Update(&ctx, text, text_len);
SHA1Final(digest, &ctx);
bzero(k_pad, sizeof k_pad);
bcopy(key, k_pad, key_len);
for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
k_pad[i] ^= 0x5c;
SHA1Init(&ctx);
SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
SHA1Final(digest, &ctx);
}
/*
* Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
* Code based on IEEE Std 802.11-2007, Annex H.4.2.
*/
int
pkcs5_pbkdf2(const char *pass, size_t pass_len, const char *salt, size_t salt_len,
u_int8_t *key, size_t key_len, u_int rounds)
{
u_int8_t *asalt, obuf[SHA1_DIGEST_LENGTH];
u_int8_t d1[SHA1_DIGEST_LENGTH], d2[SHA1_DIGEST_LENGTH];
u_int i, j;
u_int count;
size_t r;
if (rounds < 1 || key_len == 0)
return -1;
if (salt_len == 0 || salt_len > SIZE_MAX - 1)
return -1;
if ((asalt = malloc(salt_len + 4)) == NULL)
return -1;
memcpy(asalt, salt, salt_len);
for (count = 1; key_len > 0; count++) {
asalt[salt_len + 0] = (count >> 24) & 0xff;
asalt[salt_len + 1] = (count >> 16) & 0xff;
asalt[salt_len + 2] = (count >> 8) & 0xff;
asalt[salt_len + 3] = count & 0xff;
hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1);
memcpy(obuf, d1, sizeof(obuf));
for (i = 1; i < rounds; i++) {
hmac_sha1(d1, sizeof(d1), pass, pass_len, d2);
memcpy(d1, d2, sizeof(d1));
for (j = 0; j < sizeof(obuf); j++)
obuf[j] ^= d1[j];
}
r = MIN(key_len, SHA1_DIGEST_LENGTH);
memcpy(key, obuf, r);
key += r;
key_len -= r;
};
bzero(asalt, salt_len + 4);
free(asalt);
bzero(d1, sizeof(d1));
bzero(d2, sizeof(d2));
bzero(obuf, sizeof(obuf));
return 0;
}
#ifdef PBKDF2_MAIN
struct test_vector {
u_int rounds;
const char *pass;
const char *salt;
const char expected[32];
};
/*
* Test vectors from RFC 3962
*/
struct test_vector test_vectors[] = {
{
1,
"password",
"ATHENA.MIT.EDUraeburn",
{
0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01,
0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15,
0x0a, 0xd1, 0xf7, 0xa0, 0x4b, 0xb9, 0xf3, 0xa3,
0x33, 0xec, 0xc0, 0xe2, 0xe1, 0xf7, 0x08, 0x37
},
}, {
2,
"password",
"ATHENA.MIT.EDUraeburn",
{
0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e,
0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d,
0xa0, 0x53, 0x78, 0xb9, 0x32, 0x44, 0xec, 0x8f,
0x48, 0xa9, 0x9e, 0x61, 0xad, 0x79, 0x9d, 0x86
},
}, {
1200,
"password",
"ATHENA.MIT.EDUraeburn",
{
0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e,
0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b,
0xa7, 0xe5, 0x2d, 0xdb, 0xc5, 0xe5, 0x14, 0x2f,
0x70, 0x8a, 0x31, 0xe2, 0xe6, 0x2b, 0x1e, 0x13
},
}, {
5,
"password",
"\0224VxxV4\022", /* 0x1234567878563412 */
{
0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6,
0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49,
0x3f, 0x98, 0xd2, 0x03, 0xe6, 0xbe, 0x49, 0xa6,
0xad, 0xf4, 0xfa, 0x57, 0x4b, 0x6e, 0x64, 0xee
},
}, {
1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"pass phrase equals block size",
{
0x13, 0x9c, 0x30, 0xc0, 0x96, 0x6b, 0xc3, 0x2b,
0xa5, 0x5f, 0xdb, 0xf2, 0x12, 0x53, 0x0a, 0xc9,
0xc5, 0xec, 0x59, 0xf1, 0xa4, 0x52, 0xf5, 0xcc,
0x9a, 0xd9, 0x40, 0xfe, 0xa0, 0x59, 0x8e, 0xd1
},
}, {
1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"pass phrase exceeds block size",
{
0x9c, 0xca, 0xd6, 0xd4, 0x68, 0x77, 0x0c, 0xd5,
0x1b, 0x10, 0xe6, 0xa6, 0x87, 0x21, 0xbe, 0x61,
0x1a, 0x8b, 0x4d, 0x28, 0x26, 0x01, 0xdb, 0x3b,
0x36, 0xbe, 0x92, 0x46, 0x91, 0x5e, 0xc8, 0x2a
},
}, {
50,
"\360\235\204\236", /* g-clef (0xf09d849e) */
"EXAMPLE.COMpianist",
{
0x6b, 0x9c, 0xf2, 0x6d, 0x45, 0x45, 0x5a, 0x43,
0xa5, 0xb8, 0xbb, 0x27, 0x6a, 0x40, 0x3b, 0x39,
0xe7, 0xfe, 0x37, 0xa0, 0xc4, 0x1e, 0x02, 0xc2,
0x81, 0xff, 0x30, 0x69, 0xe1, 0xe9, 0x4f, 0x52
},
}
};
#define NVECS (sizeof(test_vectors) / sizeof(*test_vectors))
#include <stdio.h>
#include <err.h>
static void
printhex(const char *s, const u_int8_t *buf, size_t len)
{
size_t i;
printf("%s: ", s);
for (i = 0; i < len; i++)
printf("%02x", buf[i]);
printf("\n");
fflush(stdout);
}
int
main(int argc, char **argv)
{
u_int i, j;
u_char result[32];
struct test_vector *vec;
for (i = 0; i < NVECS; i++) {
vec = &test_vectors[i];
printf("vector %u\n", i);
for (j = 1; j < sizeof(result); j += 3) {
if (pkcs5_pbkdf2(vec->pass, strlen(vec->pass),
vec->salt, strlen(vec->salt),
result, j, vec->rounds) != 0)
errx(1, "pbkdf2 failed");
if (memcmp(result, vec->expected, j) != 0) {
printhex(" got", result, j);
printhex("want", vec->expected, j);
return 1;
}
}
}
return 0;
}
#endif /* PBKDF2_MAIN */

View File

@@ -0,0 +1,24 @@
/* $OpenBSD: pbkdf2.h,v 1.1 2008/06/14 06:28:27 djm Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
* Code based on IEEE Std 802.11-2007, Annex H.4.2.
*/
int pkcs5_pbkdf2(const char *, size_t, const char *, size_t,
u_int8_t *, size_t, u_int);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */
/**
* rijndael-alg-fst.h
*
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RIJNDAEL_H
#define __RIJNDAEL_H
#define AES_MAXKEYBITS (256)
#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
/* for 256-bit keys, fewer for less */
#define AES_MAXROUNDS 14
typedef unsigned char u_char;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
/* The structure for key information */
typedef struct {
int enc_only; /* context contains only encrypt schedule */
int Nr; /* key-length-dependent number of rounds */
u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
} rijndael_ctx;
int rijndael_set_key(rijndael_ctx *, const u_char *, int);
int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int);
void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *);
void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *);
int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
unsigned char []);
#endif /* __RIJNDAEL_H */

View File

@@ -0,0 +1,178 @@
/* $OpenBSD: sha1.c,v 1.9 2011/01/11 15:50:40 deraadt Exp $ */
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* 100% Public Domain
*
* Test Vectors (from FIPS PUB 180-1)
* "abc"
* A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
* 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
* A million repetitions of "a"
* 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include <sys/param.h>
#include <string.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void
SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned int l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
unsigned char workspace[SHA1_BLOCK_LENGTH];
block = (CHAR64LONG16 *)workspace;
bcopy(buffer, block, SHA1_BLOCK_LENGTH);
#else
block = (CHAR64LONG16 *)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
void
SHA1Init(SHA1_CTX *context)
{
/* SHA1 initialization constants */
context->count = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
}
/* Run your data through this. */
void
SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
{
unsigned int i;
unsigned int j;
j = (u_int32_t)((context->count >> 3) & 63);
context->count += (len << 3);
if ((j + len) > 63) {
bcopy(data, &context->buffer[j], (i = 64 - j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
bcopy(&data[i], &context->buffer[j], len - i);
}
/* Add padding and return the message digest. */
void
SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
{
unsigned int i;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count >>
((7 - (i & 7)) * 8)) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count & 504) != 448) {
SHA1Update(context, (unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
if (digest)
for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
digest[i] = (unsigned char)((context->state[i >> 2] >>
((3 - (i & 3)) * 8)) & 255);
}
bzero(&finalcount, 8);
#if 0 /* We want to use this for "keyfill" */
/* Wipe variables */
i = 0;
bzero(context->buffer, 64);
bzero(context->state, 20);
bzero(context->count, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
SHA1Transform(context->state, context->buffer);
#endif
#endif
}

View File

@@ -0,0 +1,26 @@
/* $OpenBSD: sha1.h,v 1.5 2007/09/10 22:19:42 henric Exp $ */
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* 100% Public Domain
*/
#ifndef _SHA1_H_
#define _SHA1_H_
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
typedef struct {
u_int32_t state[5];
u_int64_t count;
unsigned char buffer[SHA1_BLOCK_LENGTH];
} SHA1_CTX;
void SHA1Init(SHA1_CTX * context);
void SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]);
void SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len);
void SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context);
#endif /* _SHA1_H_ */

View File

@@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdint.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include "IOAESAccelerator.h"
#include "AppleEffaceableStorage.h"
#include "bsdcrypto/rijndael.h"
#include "bsdcrypto/key_wrap.h"
#include "device_info.h"
#include "registry.h"
#include "util.h"
#include "ioflash/ioflash.h"
uint8_t lockers[960]={0};
uint8_t lwvm[80]={0};
CFDictionaryRef device_info(int socket, CFDictionaryRef request)
{
uint8_t dkey[40]={0};
uint8_t emf[36]={0};
size_t bootargs_len = 255;
char bootargs[256]={0};
struct HFSInfos hfsinfos={0};
CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
get_device_infos(out);
CFMutableDictionaryRef nand = FSDGetInfo(0);
if (nand != NULL)
CFDictionaryAddValue(out, CFSTR("nand"), nand);
getHFSInfos(&hfsinfos);
uint8_t* key835 = IOAES_key835();
uint8_t* key89A = IOAES_key89A();
uint8_t* key89B = IOAES_key89B();
if (!AppleEffaceableStorage__getBytes(lockers, 960))
{
CFDataRef lockersData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, lockers, 960, kCFAllocatorNull);
CFDictionaryAddValue(out, CFSTR("lockers"), lockersData);
CFRelease(lockersData);
if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_DKEY, lockers, 960, dkey, 40))
{
aes_key_wrap_ctx ctx;
aes_key_wrap_set_key(&ctx, key835, 16);
if(aes_key_unwrap(&ctx, dkey, dkey, 32/8))
printf("FAIL unwrapping DKey with key 0x835\n");
}
if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_EMF, lockers, 960, emf, 36))
{
doAES(&emf[4], &emf[4], 32, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128);
}
else if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_LWVM, lockers, 960, lwvm, 0x50))
{
doAES(lwvm, lwvm, 0x50, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128);
memcpy(&emf[4], &lwvm[32+16], 32);
}
}
CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &hfsinfos.dataVolumeOffset);
CFDictionaryAddValue(out, CFSTR("dataVolumeOffset"), n);
CFRelease(n);
addHexaString(out, CFSTR("dataVolumeUUID"), (uint8_t*) &hfsinfos.volumeUUID, 8);
addHexaString(out, CFSTR("key835"), key835, 16);
addHexaString(out, CFSTR("key89A"), key89A, 16);
addHexaString(out, CFSTR("key89B"), key89B, 16);
addHexaString(out, CFSTR("EMF"), &emf[4], 32);
addHexaString(out, CFSTR("DKey"), dkey, 32);
sysctlbyname("kern.bootargs", bootargs, &bootargs_len, NULL, 0);
if (bootargs_len > 1)
{
CFStringRef bootargsString = CFStringCreateWithBytes(kCFAllocatorDefault, bootargs, bootargs_len - 1, kCFStringEncodingASCII, 0);
CFDictionaryAddValue(out, CFSTR("kern.bootargs"), bootargsString);
CFRelease(bootargsString);
}
CFDictionaryAddValue(out, CFSTR("ramdisk revision"), CFSTR(HGVERSION));
CFDictionaryAddValue(out, CFSTR("ramdisk compile time"), CFSTR(__DATE__ " " __TIME__ ));
return out;
}

View File

@@ -0,0 +1,5 @@
#ifndef HGVERSION
#define HGVERSION "unknown"
#endif
CFDictionaryRef device_info(int socket, CFDictionaryRef request);

View File

@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdint.h>
#include <CoreFoundation/CoreFoundation.h>
#include "device_info.h"
#include "util.h"
int main(int argc, char* argv[])
{
CFMutableDictionaryRef out = device_info(-1, NULL);
if (out == NULL)
{
fprintf(stderr, "device_info(-1, NULL) failed\n");
return -1;
}
if (argc > 1 )
{
CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingASCII);
CFTypeRef value = CFDictionaryGetValue(out, key);
if (value != NULL)
{
*stderr = *stdout;//HAX
CFShow(value);
}
else
fprintf(stderr, "key %s not found\n", argv[1]);
CFRelease(key);
CFRelease(out);
return 0;
}
writePlistToStdout(out);
/*CFStringRef plistFileName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@.plist"), CFDictionaryGetValue(out, CFSTR("dataVolumeUUID")));
CFStringRef printString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Writing results to %@\n"), plistFileName);
CFShow(printString);
CFRelease(printString);
saveResults(plistFileName, out);
CFRelease(plistFileName);*/
CFRelease(out);
return 0;
}

View File

@@ -0,0 +1,3 @@
#!/bin/sh
cat /dev/rdisk0s2s1 | netcat -l -p 1234

View File

@@ -0,0 +1,72 @@
#include <stdio.h>
#include <string.h>
#include <CoreGraphics/CoreGraphics.h>
#include <IOKit/IOKitLib.h>
int screenWidth, screenHeight;
CGContextRef context = NULL;
CGContextRef fb_open() {
io_connect_t conn = NULL;
int bytesPerRow;
void *surfaceBuffer;
void *frameBuffer;
CGColorSpaceRef colorSpace;
if (context != NULL)
return context;
io_service_t fb_service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleCLCD"));
if (!fb_service) {
fb_service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleM2CLCD"));
if (!fb_service) {
printf("Couldn't find framebuffer.\n");
return NULL;
}
}
IOMobileFramebufferOpen(fb_service, mach_task_self(), 0, &conn);
IOMobileFramebufferGetLayerDefaultSurface(conn, 0, &surfaceBuffer);
screenHeight = CoreSurfaceBufferGetHeight(surfaceBuffer);
screenWidth = CoreSurfaceBufferGetWidth(surfaceBuffer);
bytesPerRow = CoreSurfaceBufferGetBytesPerRow(surfaceBuffer);
CoreSurfaceBufferLock(surfaceBuffer, 3);
frameBuffer = CoreSurfaceBufferGetBaseAddress(surfaceBuffer);
CoreSurfaceBufferUnlock(surfaceBuffer);
// create bitmap context
colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate(frameBuffer, screenWidth, screenHeight, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
if(context == NULL) {
printf("Couldn't create screen context!\n");
return NULL;
}
CGColorSpaceRelease(colorSpace);
return context;
}
int drawImage(const char* pngFileName)
{
CGContextRef c = fb_open();
if (c == NULL)
return -1;
CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, pngFileName, strlen(pngFileName), 0);
void* imageSource = CGImageSourceCreateWithURL(url, NULL);
CFRelease(url);
if (imageSource != NULL)
{
CGImageRef img = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
if (img != NULL)
{
CGContextClearRect (c, CGRectMake(0, 0, screenWidth, screenHeight));
CGContextDrawImage(c, CGRectMake(0, 0, screenWidth, screenHeight), img);
}
}
return 0;
}

View File

@@ -0,0 +1 @@
int drawImage(const char* pngFileName);

View File

@@ -0,0 +1,556 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonCryptor.h>
#include <IOKit/IOKitLib.h>
#include "ioflash.h"
/**
used to decrypt special pages when checking if the physical banks parameter is correct
when reading/dumping pages are not decrypted
**/
uint8_t META_KEY[16] = {0x92, 0xa7, 0x42, 0xab, 0x08, 0xc9, 0x69, 0xbf, 0x00, 0x6c, 0x94, 0x12, 0xd3, 0xcc, 0x79, 0xa5};
//uint8_t FILESYSTEM_KEY[16] = {0xf6, 0x5d, 0xae, 0x95, 0x0e, 0x90, 0x6c, 0x42, 0xb2, 0x54, 0xcc, 0x58, 0xfc, 0x78, 0xee, 0xce};
uint32_t gDeviceReadID = 0;
uint32_t gCECount = 0;
uint32_t gBlocksPerCE = 0;
uint32_t gPagesPerBlock = 0;
uint32_t gBytesPerPage = 0;
uint32_t gBytesPerSpare = 0;
uint32_t gBootloaderBytes = 0;
uint32_t gIsBootFromNand = 0;
uint32_t gPagesPerCE = 0;
uint32_t gTotalBlocks = 0;
uint32_t metaPerLogicalPage = 0;
uint32_t validmetaPerLogicalPage = 0;
uint32_t banksPerCE = 0;
uint32_t use_4k_aes_chain = 0;
uint32_t gFSStartBlock= 0;
uint32_t gDumpPageSize = 0;
uint32_t gPPNdevice = 0;
uint32_t banksPerCEphysical = 1;
uint32_t bank_address_space = 0;
uint32_t blocks_per_bank = 0;
//from ioflashstoragetool
io_service_t fsdService = 0;
io_connect_t fsdConnection = 0;
CFMutableDictionaryRef MakeOneStringProp(CFStringRef key, CFStringRef value)
{
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(dict, key, value);
return dict;
}
io_service_t _wait_for_io_service_matching_dict(CFDictionaryRef matching)
{
io_service_t service = 0;
/* while(!service) {
*/CFRetain(matching);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
//if(service) break;
/*sleep(1);
//CFRelease(matching);
}
CFRelease(matching);*/
return service;
}
int FSDConnect(const char* name)
{
CFMutableDictionaryRef matching;
matching = IOServiceMatching(name);
fsdService = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
IOServiceOpen(fsdService, mach_task_self(), 0, &fsdConnection);
return fsdConnection != 0;
}
int FSDGetPropertyForKey(io_object_t obj, CFStringRef name, void* out, uint32_t outLen, CFMutableDictionaryRef dict)
{
CFTypeRef data = IORegistryEntryCreateCFProperty(obj, name, kCFAllocatorDefault, 0);
if (!data)
{
return 0;
}
if (dict != NULL)
{
CFDictionaryAddValue(dict, name, data);
}
if (out == NULL)
return 0;
if(CFGetTypeID(data) == CFNumberGetTypeID())
{
CFNumberGetValue((CFNumberRef)data, kCFNumberIntType, out);
return 1;
}
else if(CFGetTypeID(data) == CFDataGetTypeID())
{
CFIndex dataLen = CFDataGetLength(data);
CFDataGetBytes(data, CFRangeMake(0,dataLen < outLen ? dataLen : outLen), out);
return 1;
}
return 0;
}
IOReturn FSDReadPageHelper(struct kIOFlashControllerReadPageIn* in, struct kIOFlashControllerOut* out)
{
size_t outLen = sizeof(struct kIOFlashControllerOut);
IOConnectCallStructMethod(fsdConnection,
kIOFlashControllerReadPage,
in,
sizeof(struct kIOFlashControllerReadPageIn),
out,
&outLen);
// fprintf(stderr, "%x %x %x %x %x\n", in->page, in->ce, r, out->ret1, out->ret2);
return out->ret1;
}
IOReturn FSDReadPageWithOptions(uint32_t ceNum,
uint32_t pageNum,
void* buffer,
void* spareBuffer,
uint32_t spareSize,
uint32_t options,
struct kIOFlashControllerOut* out
)
{
struct kIOFlashControllerReadPageIn in;
in.page = pageNum;
in.ce = ceNum;
in.options = options;
in.buffer = buffer;
in.bufferSize = gBytesPerPage;
in.spare = spareBuffer;
in.spareSize = spareSize;
return FSDReadPageHelper(&in, out);
}
IOReturn FSDReadBootPage(uint32_t ceNum, uint32_t pageNum,uint32_t* buffer, struct kIOFlashControllerOut* out)
{
return FSDReadPageWithOptions(ceNum, pageNum, buffer, NULL, 0, kIOFlashStorageOptionBootPageIO, out);
}
void findPartitionLocation(CFStringRef contentHint, CFMutableDictionaryRef dict)
{
const void* keys[2] = {CFSTR("Block Count"), CFSTR("Block Offset")};
const void* values[2] = {NULL, NULL};
CFMutableDictionaryRef match = MakeOneStringProp(CFSTR("IOProviderClass"), CFSTR("IOFlashStoragePartition"));
CFMutableDictionaryRef iopmatch = MakeOneStringProp(CFSTR("Content Hint"), contentHint);
CFDictionarySetValue(match, CFSTR("IOPropertyMatch"), iopmatch);
CFRelease(iopmatch);
io_service_t service = _wait_for_io_service_matching_dict(match);
if (service)
{
CFNumberRef blockCount = (CFNumberRef) IORegistryEntryCreateCFProperty(service, CFSTR("Block Count"), kCFAllocatorDefault, 0);
CFNumberRef blockOffset = (CFNumberRef) IORegistryEntryCreateCFProperty(service, CFSTR("Block Offset"), kCFAllocatorDefault, 0);
if (dict != NULL)
{
values[0] = (void*) blockCount;
values[1] = (void*) blockOffset;
CFDictionaryRef d = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (d != NULL)
CFDictionaryAddValue(dict, contentHint, d);
}
if( CFStringCompare(contentHint, CFSTR("Filesystem"), 0) == kCFCompareEqualTo)
{
CFNumberGetValue(blockOffset, kCFNumberIntType, &gFSStartBlock);
}
}
CFRelease(match);
}
//openiBoot/util.c
uint32_t next_power_of_two(uint32_t n) {
uint32_t val = 1 << (31 - __builtin_clz(n));
if (n % val)
val *= 2;
return val;
}
void generate_IV(unsigned long lbn, unsigned long *iv)
{
int i;
for(i = 0; i < 4; i++)
{
if(lbn & 1)
lbn = 0x80000061 ^ (lbn >> 1);
else
lbn = lbn >> 1;
iv[i] = lbn;
}
}
void decrypt_page(uint8_t* data, uint32_t dataLength, uint8_t* key, uint32_t keyLength, uint32_t pn)
{
char iv[16];
size_t dataOutMoved=dataLength;
generate_IV(pn, (unsigned long*) iv);
CCCryptorStatus s = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
0,
(const void*) key,
keyLength,
(const void*) iv,
(const void*) data,
dataLength,
(const void*) data,
dataLength,
&dataOutMoved);
if (s != kCCSuccess)
{
fprintf(stderr, "decrypt_page: CCCrypt error %x\n", s);
}
}
void set_physical_banks(int n)
{
banksPerCEphysical = n;
blocks_per_bank = gBlocksPerCE / banksPerCEphysical;
if((gBlocksPerCE & (gBlocksPerCE-1)) == 0)
{
// Already a power of two.
bank_address_space = blocks_per_bank;
//total_block_space = gBlocksPerCE;
}
else
{
// Calculate the bank address space.
bank_address_space = next_power_of_two(blocks_per_bank);
//total_block_space = ((banksPerCEphysical-1)*bank_address_space) + blocks_per_bank;
}
}
//"bruteforce" the number of physical banks
//except for PPN devices, DEVICEINFOBBT special pages should always be somewhere at the end
void check_special_pages()
{
if(gPPNdevice)
{
fprintf(stderr, "PPN device, i don't know how to guess the number of physical banks, assuming 1\n");
set_physical_banks(1);
return;
}
uint32_t i,x=1;
uint32_t ok = 0;
uint32_t bank, block, page;
uint8_t* pageBuffer = (uint8_t*) valloc(gDumpPageSize);
printf("Searching for correct banksPerCEphysical value ...\n");
while(!ok && x < 10)
{
set_physical_banks(x);
bank = banksPerCEphysical - 1;
for(block = blocks_per_bank-1; !ok && block > blocks_per_bank-10 ; block--)
{
page = (bank_address_space * bank + block) * gPagesPerBlock;
struct kIOFlashControllerOut *out = (&pageBuffer[gBytesPerPage + metaPerLogicalPage]);
for(i=0; i < gPagesPerBlock; i++)
{
if(FSDReadPageWithOptions(0, page + i, pageBuffer, &pageBuffer[gBytesPerPage], metaPerLogicalPage, 0, out))
continue;
if(pageBuffer[gBytesPerPage] != 0xA5)
continue;
if(!memcmp(pageBuffer, "DEVICEINFOBBT", 13))
{
printf("Found cleartext DEVICEINFOBBT at block %d page %d with banksPerCEphyiscal=%d\n", blocks_per_bank*bank +block, i, banksPerCEphysical);
ok = 1;
break;
}
decrypt_page(pageBuffer, gBytesPerPage, META_KEY, kCCKeySizeAES128, page + i);
if(!memcmp(pageBuffer, "DEVICEINFOBBT", 13))
{
printf("Found encrypted DEVICEINFOBBT at block %d page %d with banksPerCEphyiscal=%d\n", blocks_per_bank*bank +block, i, banksPerCEphysical);
ok = 1;
break;
}
}
}
x++;
}
if(!ok)
{
fprintf(stderr, "Couldnt guess the number of physical banks, exiting\n");
exit(0);
}
free(pageBuffer);
return;
}
//XXX dont read the NAND from this function as it can be called from multiple processes
CFMutableDictionaryRef FSDGetInfo(int printInfo)
{
io_iterator_t iterator = 0;
io_object_t obj = 0;
FSDConnect("IOFlashController");
if(IORegistryEntryCreateIterator(fsdService, "IOService",0, &iterator))
return NULL;
obj = IOIteratorNext(iterator);
if (!obj)
return NULL;
CFMutableDictionaryRef dict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
FSDGetPropertyForKey(obj, CFSTR("device-readid"), &gDeviceReadID, sizeof(gDeviceReadID), dict);
FSDGetPropertyForKey(obj, CFSTR("#ce"), &gCECount, sizeof(gCECount), dict);
FSDGetPropertyForKey(obj, CFSTR("#ce-blocks"), &gBlocksPerCE, sizeof(gBlocksPerCE), dict);
FSDGetPropertyForKey(obj, CFSTR("#block-pages"), &gPagesPerBlock, sizeof(gPagesPerBlock), dict);
FSDGetPropertyForKey(obj, CFSTR("#page-bytes"), &gBytesPerPage, sizeof(gBytesPerPage), dict);
FSDGetPropertyForKey(obj, CFSTR("#spare-bytes"), &gBytesPerSpare, sizeof(gBytesPerSpare), dict);
FSDGetPropertyForKey(obj, CFSTR("#bootloader-bytes"), &gBootloaderBytes, sizeof(gBootloaderBytes), dict);
FSDGetPropertyForKey(obj, CFSTR("metadata-whitening"), NULL, 0, dict);
FSDGetPropertyForKey(obj, CFSTR("name"), NULL, 0, dict);
FSDGetPropertyForKey(obj, CFSTR("is-bfn-partitioned"), NULL, 0, dict);
FSDGetPropertyForKey(obj, CFSTR("bbt-format"), NULL, 0, dict);
//FSDGetPropertyForKey(obj, CFSTR("channels"), NULL, 0, dict);
FSDGetPropertyForKey(obj, CFSTR("vendor-type"), NULL, 0, dict);
FSDGetPropertyForKey(obj, CFSTR("ppn-device"), &gPPNdevice, sizeof(gPPNdevice), dict);
FSDGetPropertyForKey(obj, CFSTR("valid-meta-per-logical-page"), &validmetaPerLogicalPage, sizeof(gBytesPerSpare), dict);
FSDGetPropertyForKey(obj, CFSTR("meta-per-logical-page"), &metaPerLogicalPage, sizeof(gBytesPerSpare), dict);
if (metaPerLogicalPage == 0)
{
metaPerLogicalPage = 12;//default value?
}
//XXX: returns (possibly wrong) default value (1) when nand-disable-driver is set, use vendor-type + info from openiboot to get correct value : bank-per-ce VFL (!=physical banks)
FSDGetPropertyForKey(obj, CFSTR("banks-per-ce"), &banksPerCE, sizeof(gBytesPerSpare), dict);
FSDGetPropertyForKey(obj, CFSTR("use-4k-aes-chain"), &use_4k_aes_chain, sizeof(gBytesPerSpare), dict);
gPagesPerCE = gBlocksPerCE * gPagesPerBlock;
gTotalBlocks = gCECount * gBlocksPerCE;
FSDGetPropertyForKey(obj, CFSTR("boot-from-nand"), &gIsBootFromNand, sizeof(gIsBootFromNand), dict);
CFMutableDictionaryRef dictPartitions = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
findPartitionLocation(CFSTR("Boot Block"), dictPartitions);
findPartitionLocation(CFSTR("Effaceable"), dictPartitions);
findPartitionLocation(CFSTR("NVRAM"), dictPartitions);
findPartitionLocation(CFSTR("Firmware"), dictPartitions);
findPartitionLocation(CFSTR("Filesystem"), dictPartitions);
/*findPartitionLocation(CFSTR("Diagnostic Data"));
findPartitionLocation(CFSTR("System Config"));
findPartitionLocation(CFSTR("Bad Block Table"));*/
//findPartitionLocation(CFSTR("Unpartitioned"));//never matches
CFDictionaryAddValue(dict, CFSTR("partitions"), dictPartitions);
IOObjectRelease(obj);
IOObjectRelease(iterator);
gDumpPageSize = gBytesPerPage + metaPerLogicalPage + sizeof(struct kIOFlashControllerOut);
CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &gDumpPageSize);
CFDictionarySetValue(dict, CFSTR("dumpedPageSize"), n);
CFRelease(n);
if (printInfo)
{
uint64_t total_size = ((uint64_t)gBytesPerPage) * ((uint64_t) (gPagesPerBlock * gBlocksPerCE * gCECount));
total_size /= 1024*1024*1024;
fprintf(stderr, "NAND configuration: %uGiB (%d CEs of %d blocks of %d pages of %d bytes data, %d bytes spare\n",
(uint32_t) total_size,
gCECount,
gBlocksPerCE,
gPagesPerBlock,
gBytesPerPage,
gBytesPerSpare);
}
set_physical_banks(1);
return dict;
}
CFDictionaryRef nand_dump(int fd)
{
uint64_t totalSize = (uint64_t)gPagesPerBlock * (uint64_t)gBlocksPerCE * (uint64_t)gCECount * (uint64_t)gDumpPageSize;
write(fd, &totalSize, sizeof(uint64_t));
dump_nand_to_socket(fd);
return NULL;
}
int dump_nand_to_socket(int fd)
{
int ceNum=0,pageNum,bankNum;
IOReturn r;
uint64_t totalPages = gPagesPerBlock * gBlocksPerCE * gCECount;
uint64_t validPages = 0;
uint64_t blankPages = 0;
uint64_t errorPages = 0;
uint64_t otherPages = 0;
uint64_t counter = 0;
//page data + spare metadata + kernel return values
uint8_t* pageBuffer = (uint8_t*) valloc(gDumpPageSize);
if (pageBuffer == NULL)
{
fprintf(stderr, "valloc(%d) FAIL", gDumpPageSize);
return 0;
}
struct kIOFlashControllerOut *out = (&pageBuffer[gBytesPerPage + metaPerLogicalPage]);
time_t start = time(NULL);
for(bankNum=0; bankNum < banksPerCEphysical; bankNum++)
{
uint32_t start_page = bank_address_space * bankNum * gPagesPerBlock;
uint32_t end_page = start_page + gPagesPerBlock * blocks_per_bank;
for(pageNum=start_page; pageNum < end_page; pageNum++)
{
for(ceNum=0; ceNum < gCECount; ceNum++)
{
uint32_t blockNum = pageNum / gPagesPerBlock;
uint32_t boot = (blockNum < gFSStartBlock);
if(boot)
r = FSDReadBootPage(ceNum, pageNum, pageBuffer, out);
else
r = FSDReadPageWithOptions(ceNum, pageNum, pageBuffer, &pageBuffer[gBytesPerPage], metaPerLogicalPage, 0, out);
//r = FSDReadPageWithOptions(ceNum, pageNum, pageBuffer,NULL, 0, 0x100, out);
if(r == 0)
{
validPages++;
}
else
{
if (r == kIOReturnBadMedia)
{
fprintf(stderr, "CE %x page %x : uncorrectable ECC error\n", ceNum, pageNum);
errorPages++;
}
else if (r == kIOReturnUnformattedMedia)
{
memset(pageBuffer, 0xFF, gBytesPerPage + metaPerLogicalPage);
blankPages++;
}
else if (r == 0xdeadbeef)
{
fprintf(stderr, "0xdeadbeef return code, something is wrong with injected kernel code\n");
exit(0);
}
else if (r == kIOReturnBadArgument || r == kIOReturnNotPrivileged)
{
fprintf(stderr, "Error 0x%x (kIOReturnBadArgument/kIOReturnNotPrivileged)\n", r);
exit(0);
}
else
{
fprintf(stderr, "CE %x page %x : unknown return code 0x%x\n", ceNum, pageNum, r);
otherPages++;
}
}
out->ret2 = 0;
if(write(fd, pageBuffer, gDumpPageSize) != gDumpPageSize)
{
pageNum = gPagesPerBlock * gBlocksPerCE;
fprintf(stderr, "Abort dump\n");
break;
}
if (ceNum == 0 && pageNum % gPagesPerBlock == 0)
{
fprintf(stderr, "Block %d/%d (%d%%)\n", (counter/gPagesPerBlock), gBlocksPerCE, (counter*100)/(gPagesPerBlock*gBlocksPerCE));
}
}
counter++;
}
}
if (ceNum == gCECount && pageNum == (gPagesPerBlock * gBlocksPerCE))
{
time_t duration = time(NULL) - start;
fprintf(stderr, "Finished NAND dump in %lu hours %lu minutes %lu seconds\n", duration / 3600, (duration % 3600) / 60, (duration % 3600) % 60);
fprintf(stderr, "Total pages %llu\n", totalPages);
fprintf(stderr, "In-use pages %llu (%d%%)\n", validPages, (int) (validPages * 100 / totalPages));
fprintf(stderr, "Blank pages %llu (%d%%)\n", blankPages, (int) (blankPages * 100 / totalPages));
fprintf(stderr, "Error pages %llu (%d%%)\n", errorPages, (int) (errorPages * 100 / totalPages));
fprintf(stderr, "Other pages %llu (%d%%)\n", otherPages, (int) (otherPages * 100 / totalPages));
}
free(pageBuffer);
return 0;
}
int nand_proxy(int fd)
{
struct kIOFlashControllerOut out;
proxy_read_cmd cmd;
uint8_t* pageBuffer = (uint8_t*) valloc(gBytesPerPage);
if( pageBuffer == NULL)
{
fprintf(stderr, "pageBuffer = valloc(%d) failed\n", gBytesPerPage);
return 0;
}
while(1)
{
int z = read(fd, &cmd, sizeof(proxy_read_cmd));
if (z != sizeof(proxy_read_cmd))
break;
void* spareBuf = NULL;
uint32_t blockNum = cmd.page / gPagesPerBlock;
uint32_t boot = (blockNum < gFSStartBlock);
if(boot)
{
cmd.spareSize = 0;
cmd.options |= kIOFlashStorageOptionBootPageIO;
}
else if (cmd.spareSize)
{
spareBuf = valloc(cmd.spareSize);
}
FSDReadPageWithOptions(cmd.ce, cmd.page, pageBuffer, spareBuf, cmd.spareSize, cmd.options, &out);
write(fd, pageBuffer, gBytesPerPage);
if (spareBuf != NULL)
{
write(fd, spareBuf, cmd.spareSize);
}
write(fd, &out, sizeof(struct kIOFlashControllerOut));
if (spareBuf != NULL)
{
free(spareBuf);
}
}
free(pageBuffer);
return 0;
}

View File

@@ -0,0 +1,118 @@
#include <IOKit/IOKitLib.h>
#define kIOFlashStorageOptionBootPageIO 0x100
#define kIOFlashStorageOptionRawPageIO 0x002
#define kIOFlashStorageOptionXXXX 0x004
//0xC0 == kIOFlashStorageOptionUseAES | kIOFlashStorageOptionHomogenize
#define kIOFlashControllerReadPage 0x1
#define kIOFlashControllerWritePage 0x2
#define kIOFlashControllerDisableKeepout 0xa
struct kIOFlashControllerReadPageIn;
struct kIOFlashControllerOut;
//from ioflashstoragetool
CFMutableDictionaryRef MakeOneStringProp(CFStringRef key, CFStringRef value);
io_service_t _wait_for_io_service_matching_dict(CFDictionaryRef matching);
int FSDConnect(const char* name);
int FSDGetPropertyForKey(io_object_t obj, CFStringRef name, void* out, uint32_t outLen, CFMutableDictionaryRef dict);
void findPartitionLocation(CFStringRef contentHint, CFMutableDictionaryRef dict);//findNvramLocation
IOReturn FSDReadPageHelper(struct kIOFlashControllerReadPageIn* in, struct kIOFlashControllerOut* out);
IOReturn FSDReadPageWithOptions(uint32_t ceNum, uint32_t pageNum, void* buffer, void* spareBuffer, uint32_t spareSize, uint32_t options, struct kIOFlashControllerOut* out);
IOReturn FSDReadBootPage(uint32_t ceNum, uint32_t pageNum,uint32_t* buffer, struct kIOFlashControllerOut* out);
CFMutableDictionaryRef FSDGetInfo(int);
int IOFlashStorage_kernel_patch();
CFDictionaryRef nand_dump(int fd);
int dump_nand_to_socket(int fd);
int nand_proxy(int fd);
struct kIOFlashControllerReadPageIn
{
uint32_t page;
uint32_t ce;
uint32_t options;
void* buffer;
uint32_t bufferSize;
void* spare;
uint32_t spareSize;
};//sizeof = 0x1C
//sizeof=0x8
struct kIOFlashControllerOut
{
uint32_t ret1;
uint32_t ret2;
};
//sizeof=0x50 AppleIOPFMIDMACommand?
struct IOFlashCommandStruct
{
uint32_t flags0;
uint32_t flags1;
uint32_t field8;
uint32_t fieldC;
uint32_t* page_ptr;
void* bufferDesc;//IOMemoryDescriptor*
uint32_t field18;
uint32_t field1C;
uint32_t field20;
uint32_t* ce_ptr;
void* spareVA;
uint32_t spareSize;
uint32_t field30;
uint32_t field34;
uint32_t field38;
uint32_t errorCode;
uint32_t field40;
uint32_t field44;
uint32_t field48;
uint32_t field4C;
};
typedef struct IOExternalMethodArguments
{
uint32_t version;
uint32_t selector;
mach_port_t asyncWakePort;
io_user_reference_t * asyncReference;
uint32_t asyncReferenceCount;
const uint64_t * scalarInput;
uint32_t scalarInputCount;
const void * structureInput;
uint32_t structureInputSize;
//IOMemoryDescriptor * structureInputDescriptor;
void * structureInputDescriptor;
uint64_t * scalarOutput;
uint32_t scalarOutputCount;
void * structureOutput;
uint32_t structureOutputSize;
void * structureOutputDescriptor;
uint32_t structureOutputDescriptorSize;
uint32_t __reservedA;
//OSObject ** structureVariableOutputData;
void ** structureVariableOutputData;
uint32_t __reserved[30];
} IOExternalMethodArguments;
typedef struct proxy_read_cmd
{
uint32_t ce;
uint32_t page;
uint32_t spareSize;
uint32_t options;
} proxy_read_cmd;

View File

@@ -0,0 +1,220 @@
#include <stdio.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
#include <signal.h>
#include "ioflash.h"
CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
mach_port_t kernel_task=0;
void* externalMethod_original = NULL;
void** externalMethod_ptr = NULL;
void* (*IOMemoryDescriptor__withAddress)(void*, uint32_t, uint32_t, uint32_t) = 0x0;
typedef int (*methodptr)(void*, ...);
#define CALL_VTABLE(this, vtableoff, ...) \
((methodptr) (*(uint32_t**)this)[vtableoff/4]) (this, ##__VA_ARGS__)
//IOReturn externalMethod( uint32_t selector, IOExternalMethodArguments * arguments,IOExternalMethodDispatch * dispatch = 0, OSObject * target = 0, void * reference = 0 );
int myIOFlashStorage_externalMethod(uint32_t* this, uint32_t selector, IOExternalMethodArguments* arguments)
{
if (selector == kIOFlashControllerDisableKeepout)
{
void* obj2 = (void*) this[0x78/4]; //AppleIOPFMI object
CALL_VTABLE(obj2, 0x35C, 0, 0, 1);
return 0x0;
}
if (selector != kIOFlashControllerReadPage) //only support read
return 0xE00002C2;
if (IOMemoryDescriptor__withAddress == 0x0)
return 0xdeadbeef;
struct IOFlashCommandStruct command = {0};
uint32_t** bufferDesc = NULL;
uint32_t** spareDesc = NULL;
uint32_t** md = NULL;
void* obj1 = (void*) this[0x78/4]; //AppleIOPFMI object
struct kIOFlashControllerReadPageIn* in = (struct kIOFlashControllerReadPageIn*) arguments->structureInput;
struct kIOFlashControllerOut* out = (struct kIOFlashControllerOut*) arguments->structureOutput;
uint32_t page = in->page;
uint32_t ce = in->ce;
command.flags1 = 1;
if (in->options & kIOFlashStorageOptionBootPageIO)
{
if(in->spare != NULL)
return 0xE00002C2; //spare buffer is not used with bootloader page I/O
command.flags0 = 9;
}
else
{
if( !(in->options & kIOFlashStorageOptionRawPageIO) && in->spare)
{
command.flags0 = in->options & 2;
}
else
{
return 0xdeadbeef; //raw page io
}
}
command.flags1 |= in->options & 4;
command.field8 = 1;
command.fieldC = 0;
command.page_ptr = &page;
bufferDesc = IOMemoryDescriptor__withAddress(in->buffer, in->bufferSize, 1, this[0x7C/4]);
if (bufferDesc == NULL)
return 0xE00002C2;
command.bufferDesc = bufferDesc;
command.field18 = 0;
command.errorCode = 0;
if (in->spare != NULL)
{
spareDesc = IOMemoryDescriptor__withAddress(in->spare, in-> spareSize, 1, this[0x7C/4]);
if (spareDesc == NULL)
return 0xE00002C2;
//0xAC -> desc2 __ZN25IOGeneralMemoryDescriptor5doMapEP7_vm_mapPjmmm
//virtual IOMemoryMap * map( IOOptionBits options = 0 );
md = (void*) CALL_VTABLE(spareDesc, 0x98); //IOGeneralMemoryDescriptor_map
command.spareSize = in->spareSize;
command.spareVA = (void*) CALL_VTABLE(md, 0x38);
}
else
{
command.spareSize = 0;
command.spareVA = NULL;
}
command.field34 = 0;
command.ce_ptr = &ce;
out->ret1 = CALL_VTABLE(obj1, 0x344, 0, &command);
CALL_VTABLE(bufferDesc, 0x14); //IOGeneralMemoryDescriptor_release
if (md != NULL)
{
CALL_VTABLE(md, 0x14); //IOGeneralMemoryDescriptor_release
}
if (spareDesc != NULL)
{
CALL_VTABLE(spareDesc, 0x14); //IOGeneralMemoryDescriptor_release
}
out->ret2 = command.errorCode;
return 0;
}
kern_return_t write_kernel(mach_port_t p, void* addr, uint32_t value)
{
kern_return_t r = vm_write(p, (vm_address_t)addr, (vm_address_t)&value, sizeof(value ));
if (r)
fprintf(stderr, "vm_write into kernel_task failed\n");
else
fprintf(stderr, "vm_write into kernel_task OK\n");
return r;
}
void __attribute__((destructor)) restore_handler()
{
if (kernel_task != 0 && externalMethod_ptr != NULL && externalMethod_original != NULL)
{
fprintf(stderr, "Restoring IOFlashStorageControler::externalMethod ptr\n");
write_kernel(kernel_task, externalMethod_ptr, (uint32_t) externalMethod_original+1);
}
}
void signal_handler(int sig)
{
restore_handler();
signal(sig, SIG_DFL);
raise(sig);
}
int IOFlashStorage_kernel_patch()
{
CFStringRef version = NULL;
CFDictionaryRef versionDict = _CFCopySystemVersionDictionary();
if (versionDict != NULL)
{
version = CFDictionaryGetValue(versionDict, _kCFSystemVersionProductVersionKey);
}
if (version == NULL)
{
fprintf(stderr, "FAILed to get current version\n");
return 0;
}
if (CFStringCompare(version, CFSTR("4.3.5"), 0) <= 0)
{
fprintf(stderr, "iOS 4 kernel detected, no kernel patching required\n");
return 1;
}
fprintf(stderr, "iOS 5 kernel detected, replacing IOFlashControlerUserClient::externalMethod\n");
kern_return_t r = task_for_pid(mach_task_self(), 0, &kernel_task);
if( r != 0)
{
fprintf(stderr, "task_for_pid returned %x : missing tfp0 kernel patch (use latest kernel_patcher.py) or wrong entitlements\n", r);
return 0;
}
uint32_t i;
pointer_t buf;
unsigned int sz;
vm_address_t addr = 0x80002000;
while( addr < (0x80002000 + 0xA00000))
{
vm_read(kernel_task, addr, 2048, &buf, &sz);
if( buf == NULL || sz == 0)
continue;
uint32_t* p = (uint32_t*) buf;
for(i=0; i < sz/sizeof(uint32_t); i++)
{
if (externalMethod_original != NULL)
{
if (p[i] == (externalMethod_original+1))
{
externalMethod_ptr = (void*) (addr + i*4);
fprintf(stderr, "Found externalMethod ptr at %x\n", (uint32_t) externalMethod_ptr);
write_kernel(kernel_task, externalMethod_ptr, (uint32_t) myIOFlashStorage_externalMethod);
signal(SIGINT, signal_handler);//handle ctrl+c
return 1;
}
else if(IOMemoryDescriptor__withAddress == NULL && !memcmp(&p[i], "\x20\x46\x26\xB0\x5D\xF8\x04\x8B\xF0\xBD", 10))
{
IOMemoryDescriptor__withAddress = (void*) p[i+5];
fprintf(stderr, "IOMemoryDescriptor__withAddress=%x\n", (uint32_t) IOMemoryDescriptor__withAddress);
}
}
else if(!memcmp(&p[i], "\xF0\xB5\x03\xAF\x4D\xF8\x04\x8D\xA6\xB0\x40\xF2\xC2\x24\x13\x6A", 16))
{
externalMethod_original = (void*) (addr + i*4);
fprintf(stderr, "Found IOFlashControlerUserClient::externalMethod at %x\n", (uint32_t) externalMethod_original);
}
}
addr += 2048;
}
fprintf(stderr, "Kernel patching failed\n");
return 0;
}

View File

@@ -0,0 +1,59 @@
#include <stdio.h>
#include <sys/socket.h>
#include <CoreFoundation/CoreFoundation.h>
#include "ioflash.h"
#include "../util.h"
#define LISTEN_PORT 2000
#define CMD_DUMP 0
#define CMD_PROXY 1
int main(int argc, char* argv[])
{
int one=1;
int cmd=0;
if(!IOFlashStorage_kernel_patch())
return -1;
CFMutableDictionaryRef dict = FSDGetInfo(1);
if(dict == NULL)
{
fprintf(stderr, "FAILed to get NAND infos");
return -1;
}
check_special_pages();
int sl = create_listening_socket(LISTEN_PORT);
if(sl == -1)
{
fprintf(stderr, "Error calling create_listening_socket\n");
return -1;
}
fprintf(stderr, "NAND dumper listening on port %d\n", LISTEN_PORT);
while(1)
{
int s = accept(sl, NULL, NULL);
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(int));
int r = read(s, (void*) &cmd, sizeof(int));
if(r == sizeof(int))
{
if(cmd == CMD_DUMP)
{
nand_dump(s);
}
else if(cmd == CMD_PROXY)
{
nand_proxy(s);
}
}
shutdown(s, SHUT_RDWR);
close(s);
}
return 0;
}

View File

@@ -0,0 +1,72 @@
#include <stdio.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
mach_port_t kernel_task=0;
kern_return_t write_kernel(mach_port_t p, void* addr, uint32_t value)
{
pointer_t buf;
unsigned int sz;
kern_return_t r = vm_write(p, (vm_address_t)addr, (vm_address_t)&value, sizeof(value));
if (r)
{
fprintf(stderr, "vm_write into kernel_task failed\n");
}
else
{
//fix cache issue
vm_read(p, (vm_address_t) addr, sizeof(value), &buf, &sz);
fprintf(stderr, "vm_write into kernel_task OK %x\n", *((uint32_t*) buf));
}
return r;
}
int patch_IOAESAccelerator()
{
kern_return_t r = task_for_pid(mach_task_self(), 0, &kernel_task);
if( r != 0)
{
fprintf(stderr, "task_for_pid returned %x : missing tfp0 kernel patch or wrong entitlements\n", r);
return 0;
}
uint32_t i;
pointer_t buf;
unsigned int sz;
vm_address_t addr = 0x80002000;
while( addr < (0x80002000 + 0xA00000))
{
vm_read(kernel_task, addr, 2048, &buf, &sz);
if( buf == NULL || sz == 0)
continue;
uint8_t* p = (uint8_t*) buf;
for(i=0; i < sz; i++)
{
//"IOAESAccelerator enable UID" : (h("67 D0 40 F6"), h("00 20 40 F6")),
if (*((uint32_t*)&p[i]) == 0xF640d067)
{
fprintf(stderr, "Found IOAESAccelerator UID ptr at %x, patching kernel\n", (uint32_t) addr + i);
write_kernel(kernel_task, (void*) (addr + i), (uint32_t) 0xF6402000);
return 0;
}
}
addr += 2048;
}
fprintf(stderr, "IOAESAccelerator Kernel patching failed\n");
return -1;
}
/*
int main(int argc, char** argv)
{
return patch_IOAESAccelerator();
}
*/

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.keystore.device</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,159 @@
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include "plist_server.h"
#include "util.h"
#define TCP_PORT 1999
int send_progress_message(int socket, int progress, int total)
{
const void* keys[3] = {CFSTR("MessageType"), CFSTR("Progress"), CFSTR("Total")};
const void* values[3] = {CFSTR("Progress"), NULL, NULL};
CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &progress);
CFNumberRef number2 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &total);
values[1] = number;
values[2] = number2;
CFDictionaryRef msg = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFRelease(number);
CFRelease(number2);
int res = send_object(socket, msg);
CFRelease(msg);
return res;
}
int send_object(int socket, CFTypeRef obj)
{
uint32_t len = 0;
int res = -1;
if(obj == NULL)
return res;
CFDataRef outdata = CFPropertyListCreateData(kCFAllocatorDefault, obj, kCFPropertyListXMLFormat_v1_0, 0, NULL);
if (outdata != NULL)
{
len = CFDataGetLength(outdata);
write(socket, &len, 4);
res = write(socket, CFDataGetBytePtr(outdata), CFDataGetLength(outdata));
CFRelease(outdata);
}
return res;
}
int handle_client(int socket, CFDictionaryRef handlers)
{
uint32_t len=0;
uint32_t received,i;
CFDataRef data;
CFDictionaryRef plist;
CFTypeRef out = NULL;
uint8_t* buffer;
CFTypeRef (*handler)(int, CFDictionaryRef dict) = NULL;
while(1)
{
if(recv(socket, &len, 4, 0) != 4)
break;
//printf("len=%x\n", len);
if (len > PLIST_MAX_SIZE)
break;
buffer = malloc(len);
if(buffer == NULL)
break;
for(i=0; i < len; )
{
received = recv(socket, &buffer[i], len - i, 0);
if (received == -1)
break;
i += received;
}
data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buffer, len, kCFAllocatorNull);
if(data == NULL)
{
free(buffer);
continue;
}
plist = (CFDictionaryRef) CFPropertyListCreateWithData (kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, NULL);
if(plist == NULL || CFGetTypeID(plist) != CFDictionaryGetTypeID())
{
CFRelease(data);
free(buffer);
send_object(socket, CFSTR("invalid XML plist dictionary"));
continue;
}
if (CFDictionaryContainsKey(plist, CFSTR("Request")))
{
CFStringRef request = CFDictionaryGetValue(plist, CFSTR("Request"));
handler = CFDictionaryGetValue(handlers, request);
if (handler != NULL)
{
out = handler(socket, plist);
if (out == NULL)
out = CFSTR("Request did not return any result");
}
else
{
out = CFSTR("No handler defined for Request");
}
}
else
{
out = CFSTR("request dictionary needs to contain Request key");
}
if(out == NULL)
out = CFSTR("no response");
send_object(socket, out);
CFRelease(out);
CFRelease(plist);
CFRelease(data);
free(buffer);
}
send_object(socket, CFSTR("kthxbye"));
return 0;
}
void serve_plist_rpc(int port, CFDictionaryRef handlers)
{
int quit = 0;
int one=1;
printf("plist_rpc: listening on port %d\n", port);
int sl = create_listening_socket(port);
while(!quit)
{
int s = accept(sl, NULL, NULL);
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(int));
handle_client(s, handlers);
shutdown(s, SHUT_RDWR);
close(s);
}
close(sl);
}
CFStringRef testHandler(int s, CFDictionaryRef dict)
{
printf("lol\n");
return CFSTR("Hello, World!");
}

View File

@@ -0,0 +1,6 @@
#define PLIST_MAX_SIZE 50*1024*1024
int create_listening_socket(int port);
int send_progress_message(int socket, int progress, int total);
int send_object(int socket, CFTypeRef obj);
void serve_plist_rpc(int port, CFDictionaryRef handlers);

View File

@@ -0,0 +1,423 @@
/**
https://github.com/Gojohnnyboi/restored_pwn
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <CommonCrypto/CommonDigest.h>
#include "util.h"
//from libmobilegestalt.dylib
CFDataRef copyDataFromChosen(CFStringRef key)
{
io_registry_entry_t chosen = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/chosen");
if (chosen)
{
CFDataRef res = IORegistryEntryCreateCFProperty(chosen, key, kCFAllocatorDefault, 0);
IOObjectRelease(chosen);
return res;
}
return NULL;
}
CFStringRef copyStringFromChosen(CFStringRef key)
{
CFStringRef s = NULL;
CFDataRef data = copyDataFromChosen(key);
if(data == NULL)
return NULL;
if(CFGetTypeID(data) == CFDataGetTypeID())
{
s = CFStringCreateWithCString(kCFAllocatorDefault, (const char*) CFDataGetBytePtr(data), kCFStringEncodingUTF8);
}
CFRelease(data);
return s;
}
CFNumberRef copyNumberFromChosen(CFStringRef key)
{
CFNumberRef num = NULL;
CFDataRef data = copyDataFromChosen(key);
if(data == NULL)
return NULL;
if(CFGetTypeID(data) == CFDataGetTypeID())
{
int len = CFDataGetLength(data);
num = CFNumberCreate(kCFAllocatorDefault,
len == 4 ? kCFNumberSInt32Type : kCFNumberSInt64Type,
CFDataGetBytePtr(data)
);
}
CFRelease(data);
return num;
}
io_service_t get_io_service(const char *name) {
CFMutableDictionaryRef matching;
io_service_t service = 0;
matching = IOServiceMatching(name);
if(matching == NULL) {
printf("unable to create matching dictionary for class '%s'\n", name);
return 0;
}
while(!service) {
CFRetain(matching);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
if(service) break;
printf("waiting for matching IOKit service: %s\n", name);
sleep(1);
CFRelease(matching);
}
CFRelease(matching);
return service;
}
CFStringRef copy_device_imei() {
CFMutableDictionaryRef matching;
io_service_t service;
CFDataRef imeiData;
const void *imeiDataPtr;
CFStringRef imeiString;
matching = IOServiceNameMatching("baseband");
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
if(!service) {
return NULL;
}
imeiData = IORegistryEntryCreateCFProperty(service, CFSTR("device-imei"), kCFAllocatorDefault, 0);
if(!imeiData) {
printf("unable to find device-imei property\n");
IOObjectRelease(service);
return NULL;
}
imeiDataPtr = CFDataGetBytePtr(imeiData);
imeiString = CFStringCreateWithCString(kCFAllocatorDefault, imeiDataPtr, kCFStringEncodingUTF8);
CFRelease(imeiData);
IOObjectRelease(service);
return imeiString;
}
CFStringRef copy_device_serial_number() {
io_service_t service;
CFStringRef serialNumber;
service = get_io_service("IOPlatformExpertDevice");
if(!service) {
printf("unable to find IOPlatformExpertDevice service\n");
return NULL;
}
serialNumber = IORegistryEntryCreateCFProperty(service, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
IOObjectRelease(service);
return serialNumber;
}
CFStringRef copy_devicetree_option(CFStringRef key) {
io_registry_entry_t entry;
CFStringRef option;
entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
if(!entry) {
printf("unable to get registry entry for IODeviceTree:/options\n");
return NULL;
}
option = IORegistryEntryCreateCFProperty(entry, key, kCFAllocatorDefault, 0);
IOObjectRelease(entry);
return option;
}
CFStringRef copy_hardware_model() {
size_t buflen = 0x80;
char buf[buflen];
CFStringRef model;
if(sysctlbyname("hw.model", buf, &buflen, NULL, 0) != 0) {
printf("sysctlbyname for hw.model failed: %s\n", strerror(errno));
return NULL;
}
model = CFStringCreateWithCString(kCFAllocatorDefault, buf, kCFStringEncodingUTF8);
return model;
}
CFStringRef copy_hardware_platform() {
io_service_t service;
CFStringRef platform;
char *platformPtr;
service = get_io_service("IOPlatformExpertDevice");
if(!service) {
printf("unable to find IOPlatformExpertDevice service\n");
return NULL;
}
platform= IORegistryEntryCreateCFProperty(service, CFSTR("platform-name"), kCFAllocatorDefault, 0);
if(platform == NULL) {
printf("platform-name not found in device tree\n");
IOObjectRelease(service);
return NULL;
}
platformPtr = calloc(1, CFStringGetLength(platform)+1);
if(!CFStringGetCString(platform, platformPtr, CFStringGetLength(platform)+1, kCFStringEncodingUTF8)) {
printf("unable to obtain platform-name string\n");
IOObjectRelease(service);
return NULL;
}
printf("platform-name = %s\n", platformPtr);
free(platformPtr);
return platform;
}
CFStringRef copy_bluetooth_mac_address() {
io_service_t service;
CFDataRef macaddrData;
CFStringRef macaddr;
unsigned char macaddrBytes[6];
service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("bluetooth"));
if(!service) {
printf("unable to find bluetooth service\n");
return NULL;
}
macaddrData= IORegistryEntryCreateCFProperty(service, CFSTR("local-mac-address"), kCFAllocatorDefault, 0);
if(macaddrData == NULL) {
printf("bluetooth local-mac-address not found\n");
IOObjectRelease(service);
return NULL;
}
CFDataGetBytes(macaddrData, CFRangeMake(0,6), macaddrBytes);
macaddr = CFStringCreateWithFormat(kCFAllocatorDefault,
NULL,
CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"),
macaddrBytes[0],
macaddrBytes[1],
macaddrBytes[2],
macaddrBytes[3],
macaddrBytes[4],
macaddrBytes[5]);
return macaddr;
}
void search_wifi_mac_callback(void** context, io_iterator_t iterator) {
unsigned char macaddrBytes[6];
io_iterator_t iterator2=0;
io_object_t obj2=0;
io_name_t name;
CFDataRef t1=0;
io_object_t next;
while ((next = IOIteratorNext(iterator)) != 0)
{
if (!IORegistryEntryCreateIterator(next, "IOService", 3, &iterator2))
{
while((obj2 = IOIteratorNext(iterator2)) != 0)
{
if (!IORegistryEntryGetName(obj2,name))
{
if (!strcmp(name, "sdio") || !strcmp(name, "wlan"))
{
if((t1 = IORegistryEntryCreateCFProperty(obj2, CFSTR("local-mac-address"), kCFAllocatorDefault, 0)) != 0)
{
CFDataGetBytes(t1, CFRangeMake(0,6), macaddrBytes);
*context = (void*) CFStringCreateWithFormat(kCFAllocatorDefault,
NULL,
CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"),
macaddrBytes[0],
macaddrBytes[1],
macaddrBytes[2],
macaddrBytes[3],
macaddrBytes[4],
macaddrBytes[5]);
CFRelease(t1);
}
}
}
}
IOObjectRelease(iterator2);
}
IOObjectRelease(next);
if (*context != NULL)
break;
}
}
CFStringRef lookup_mac_address(const char* serviceName)
{
unsigned char macaddrBytes[6];
CFStringRef res = NULL;
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching(serviceName));
if(service)
{
CFDataRef macData = IORegistryEntryCreateCFProperty(service, CFSTR("local-mac-address"), kCFAllocatorDefault, 0);
if(macData != NULL)
{
CFDataGetBytes(macData, CFRangeMake(0,6), macaddrBytes);
res = CFStringCreateWithFormat(kCFAllocatorDefault,
NULL,
CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"),
macaddrBytes[0],
macaddrBytes[1],
macaddrBytes[2],
macaddrBytes[3],
macaddrBytes[4],
macaddrBytes[5]);
CFRelease(macData);
}
IOObjectRelease(service);
}
return res;
}
CFStringRef copy_wifi_mac_address() {
CFStringRef wifimac = NULL;
IONotificationPortRef notify_port = 0;
io_iterator_t iterator = 0;
wifimac = lookup_mac_address("sdio");
if (wifimac != NULL)
return wifimac;
wifimac = lookup_mac_address("wlan");
if (wifimac != NULL)
return wifimac;
notify_port = IONotificationPortCreate(kIOMasterPortDefault);
CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notify_port);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
if (!IOServiceAddMatchingNotification( notify_port,
kIOMatchedNotification,
IOServiceMatching("IONetworkController"),
(IOServiceMatchingCallback) search_wifi_mac_callback,
&wifimac,
&iterator
))
{
search_wifi_mac_callback((void**)&wifimac, iterator);
while( wifimac == NULL)
{
if( CFRunLoopRunInMode(kCFRunLoopDefaultMode,0, TRUE) != kCFRunLoopRunHandledSource)
{
printf("giving up on wifi mac address\n");
break;
}
}
}
IONotificationPortDestroy(notify_port);
return wifimac;
}
int useNewUDID(CFStringRef hw)
{
return CFEqual(hw, CFSTR("K93AP")) ||
CFEqual(hw, CFSTR("K94AP")) ||
CFEqual(hw, CFSTR("K95AP")) ||
CFEqual(hw, CFSTR("N92AP")) ||
CFEqual(hw, CFSTR("N94AP"));
}
//http://iphonedevwiki.net/index.php/Lockdownd
void get_device_infos(CFMutableDictionaryRef out) {
CC_SHA1_CTX sha1ctx;
uint8_t udid[20];
char udid1[100];
CFStringRef serial;
CFStringRef imei;
CFStringRef macwifi;
CFStringRef macbt;
CFStringRef hw = copy_hardware_model();
if (hw != NULL)
{
CFDictionaryAddValue(out, CFSTR("hwModel"), hw);
CFRelease(hw);
}
serial = copy_device_serial_number();
imei = copy_device_imei();
macwifi = copy_wifi_mac_address();
macbt = copy_bluetooth_mac_address();
CFMutableStringRef udidInput = CFStringCreateMutable(kCFAllocatorDefault, 0);
if (serial != NULL)
{
CFStringAppend(udidInput, serial);
CFDictionaryAddValue(out, CFSTR("serialNumber"), serial);
CFRelease(serial);
}
uint64_t _ecid = 0;
CFNumberRef ecid = copyNumberFromChosen(CFSTR("unique-chip-id"));
if (ecid != NULL)
{
CFDictionaryAddValue(out, CFSTR("ECID"), ecid);
}
if (ecid != NULL && useNewUDID(hw))
{
CFNumberGetValue(ecid, kCFNumberSInt64Type, &_ecid);
CFStringAppendFormat(udidInput, NULL, CFSTR("%llu"), _ecid);
}
else if (imei != NULL)
{
CFStringAppend(udidInput, imei);
CFDictionaryAddValue(out, CFSTR("imei"), imei);
CFRelease(imei);
}
if (macwifi != NULL)
{
CFStringAppend(udidInput, macwifi);
CFDictionaryAddValue(out, CFSTR("wifiMac"), macwifi);
CFRelease(macwifi);
}
if (macbt != NULL)
{
CFStringAppend(udidInput, macbt);
CFDictionaryAddValue(out, CFSTR("btMac"), macbt);
CFRelease(macbt);
}
CFStringGetCString(udidInput, udid1, 99, kCFStringEncodingASCII);
CC_SHA1_Init(&sha1ctx);
CC_SHA1_Update(&sha1ctx, udid1, CFStringGetLength(udidInput));
CC_SHA1_Final(udid, &sha1ctx);
CFRelease(udidInput);
addHexaString(out, CFSTR("udid"), udid, 20);
}

View File

@@ -0,0 +1 @@
void get_device_infos(CFMutableDictionaryRef out);

View File

@@ -0,0 +1,282 @@
#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;
}

View File

@@ -0,0 +1,7 @@
CFDictionaryRef load_system_keybag(int socket, CFDictionaryRef dict);
CFDictionaryRef bruteforce_system_keybag(int socket, CFDictionaryRef dict);
CFDictionaryRef keybag_get_passcode_key(int socket, CFDictionaryRef dict);
CFDictionaryRef get_escrow_record(int socket, CFDictionaryRef dict);
CFDictionaryRef download_file(int socket, CFDictionaryRef dict);
CFDictionaryRef remote_aes(int socket, CFDictionaryRef dict);

View File

@@ -0,0 +1,269 @@
/**
https://github.com/comex/bloggy/wiki/Redsn0w%2Busbmux
**/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <spawn.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <assert.h>
#include <CoreFoundation/CoreFoundation.h>
#include <AvailabilityMacros.h>
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_5
#include <IOKit/IOCFPlugIn.h>
#include "IOUSBDeviceControllerLib.h"
#include "plist_server.h"
#include "remote_functions.h"
#include "device_info.h"
#include "registry.h"
#define kIOSomethingPluginID CFUUIDGetConstantUUIDWithBytes(NULL, \
0x9E, 0x72, 0x21, 0x7E, 0x8A, 0x60, 0x11, 0xDB, \
0xBF, 0x57, 0x00, 0x0D, 0x93, 0x6D, 0x06, 0xD2)
#define kIOWhatTheFuckID CFUUIDGetConstantUUIDWithBytes(NULL, \
0xEA, 0x33, 0xBA, 0x4F, 0x8A, 0x60, 0x11, 0xDB, \
0x84, 0xDB, 0x00, 0x0D, 0x93, 0x6D, 0x06, 0xD2)
void init_usb(CFStringRef serialString) {
IOUSBDeviceDescriptionRef desc = IOUSBDeviceDescriptionCreateFromDefaults(kCFAllocatorDefault);
IOUSBDeviceDescriptionSetSerialString(desc, serialString == NULL ? CFSTR("ramdisk - udid fail?") : serialString);
CFArrayRef usb_interfaces = IOUSBDeviceDescriptionCopyInterfaces(desc);
int i;
for(i=0; i < CFArrayGetCount(usb_interfaces); i++)
{
CFArrayRef arr1 = CFArrayGetValueAtIndex(usb_interfaces, i);
if( CFArrayContainsValue(arr1, CFRangeMake(0,CFArrayGetCount(arr1)), CFSTR("PTP")))
{
printf("Found PTP interface\n");
break;
}
}
IOUSBDeviceControllerRef controller;
while (IOUSBDeviceControllerCreate(kCFAllocatorDefault, &controller))
{
printf("Unable to get USB device controller\n");
sleep(3);
}
IOUSBDeviceControllerSetDescription(controller, desc);
CFMutableDictionaryRef match = IOServiceMatching("IOUSBDeviceInterface");
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(dict, CFSTR("USBDeviceFunction"), CFSTR("PTP"));
CFDictionarySetValue(match, CFSTR("IOPropertyMatch"), dict);
io_service_t service;
while(1) {
service = IOServiceGetMatchingService(kIOMasterPortDefault, match);
if(!service) {
printf("Didn't find, trying again\n");
sleep(1);
} else {
break;
}
}
IOCFPlugInInterface **iface;
SInt32 score;
printf("123\n");
assert(!IOCreatePlugInInterfaceForService(
service,
kIOSomethingPluginID,
kIOCFPlugInInterfaceID,
&iface,
&score
));
void *thing;
assert(!((*iface)->QueryInterface)(iface,
CFUUIDGetUUIDBytes(kIOWhatTheFuckID),
&thing));
IOReturn (**table)(void *, ...) = *((void **) thing);
printf("%p\n", table[0x10/4]);
//open IOUSBDeviceInterfaceInterface
(!table[0x10/4](thing, 0));
//set IOUSBDeviceInterfaceInterface class
(!table[0x2c/4](thing, 0xff, 0));
//set IOUSBDeviceInterfaceInterface sub-class
(!table[0x30/4](thing, 0x50, 0));
//set IOUSBDeviceInterfaceInterface protocol
(!table[0x34/4](thing, 0x43, 0));
//commit IOUSBDeviceInterfaceInterface configuration
(!table[0x44/4](thing, 0));
IODestroyPlugInInterface(iface);
//assert(!table[0x14/4](thing, 0));
}
void init_tcp() {
// from launchd
struct ifaliasreq ifra;
struct ifreq ifr;
int s;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, "lo0");
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
return;
if (ioctl(s, SIOCGIFFLAGS, &ifr) != -1) {
ifr.ifr_flags |= IFF_UP;
assert(ioctl(s, SIOCSIFFLAGS, &ifr) != -1);
}
memset(&ifra, 0, sizeof(ifra));
strcpy(ifra.ifra_name, "lo0");
((struct sockaddr_in *)&ifra.ifra_addr)->sin_family = AF_INET;
((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
((struct sockaddr_in *)&ifra.ifra_addr)->sin_len = sizeof(struct sockaddr_in);
((struct sockaddr_in *)&ifra.ifra_mask)->sin_family = AF_INET;
((struct sockaddr_in *)&ifra.ifra_mask)->sin_addr.s_addr = htonl(IN_CLASSA_NET);
((struct sockaddr_in *)&ifra.ifra_mask)->sin_len = sizeof(struct sockaddr_in);
assert(ioctl(s, SIOCAIFADDR, &ifra) != -1);
assert(close(s) == 0);
}
CFDictionaryRef reboot__(int socket, CFDictionaryRef dict)
{
reboot(0);
return NULL;
}
char* execve_env[]= {NULL};
char* execve_params[]={"/sbin/sshd", NULL};
char* ioflash[]={"/var/root/ioflashstoragekit", NULL};
size_t bootargs_len = 255;
char bootargs[256]={0};
int main(int argc, char* argv[])
{
int i;
int nandReadOnly=0;
struct stat st;
printf("Starting ramdisk tool\n");
printf("Compiled " __DATE__ " " __TIME__ "\n");
printf("Revision " HGVERSION "\n");
CFMutableDictionaryRef matching;
io_service_t service = 0;
matching = IOServiceMatching("IOWatchDogTimer");
if (matching == NULL) {
printf("unable to create matching dictionary for class IOWatchDogTimer\n");
}
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
if (service == 0) {
printf("unable to create matching dictionary for class IOWatchDogTimer\n");
}
uint32_t zero = 0;
CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero);
IORegistryEntrySetCFProperties(service, n);
IOObjectRelease(service);
CFMutableDictionaryRef deviceInfos = CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
get_device_infos(deviceInfos);
init_tcp();
sysctlbyname("kern.bootargs", bootargs, &bootargs_len, NULL, 0);
if (strstr(bootargs, "nand-readonly") || strstr(bootargs, "nand-disable"))
{
printf("NAND read only mode, data partition wont be mounted\n");
nandReadOnly = 1;
}
else
{
printf("Waiting for data partition\n");
for(i=0; i < 10; i++)
{
if(!stat("/dev/disk0s2s1", &st))
{
system("/sbin/fsck_hfs /dev/disk0s2s1");
break;
}
if(!stat("/dev/disk0s1s2", &st))
{
system("/sbin/fsck_hfs /dev/disk0s1s2");
break;
}
if(!stat("/dev/disk0s2", &st))
{
system("/sbin/fsck_hfs /dev/disk0s2");
break;
}
sleep(5);
}
}
init_usb(CFDictionaryGetValue(deviceInfos, CFSTR("udid")));
printf("USB init done\n");
system("mount /"); //make ramdisk writable
chmod("/var/root/.ssh/authorized_keys", 0600);
chown("/var/root/.ssh/authorized_keys", 0, 0);
chown("/var/root/.ssh", 0, 0);
chown("/var/root/", 0, 0);
printf(" ####### ## ##\n");
printf("## ## ## ## \n");
printf("## ## ## ## \n");
printf("## ## ##### \n");
printf("## ## ## ## \n");
printf("## ## ## ## \n");
printf(" ####### ## ##\n");
printf("iphone-dataprotection ramdisk\n");
printf("revision: " HGVERSION " " __DATE__ " " __TIME__ "\n");
if(!stat(execve_params[0], &st))
{
printf("Running %s\n", execve_params[0]);
if((i = posix_spawn(NULL, execve_params[0], NULL, NULL, execve_params, execve_env)))
printf("posix_spawn(%s) returned %d\n", execve_params[0], i);
}
else
{
printf("%s is missing\n", execve_params[0]);
}
/*if (nandReadOnly)
{*/
if(!stat(ioflash[0], &st))
{
printf("Running %s\n", ioflash[0]);
if((i = posix_spawn(NULL, ioflash[0], NULL, NULL, ioflash, execve_env)))
printf("posix_spawn(%s) returned %d\n", execve_params[0], i);
}
/*}*/
CFMutableDictionaryRef handlers = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
CFDictionaryAddValue(handlers, CFSTR("DeviceInfo"), device_info);
CFDictionaryAddValue(handlers, CFSTR("GetSystemKeyBag"), load_system_keybag);
CFDictionaryAddValue(handlers, CFSTR("BruteforceSystemKeyBag"), bruteforce_system_keybag);
CFDictionaryAddValue(handlers, CFSTR("KeyBagGetPasscodeKey"), keybag_get_passcode_key);
CFDictionaryAddValue(handlers, CFSTR("GetEscrowRecord"), get_escrow_record);
CFDictionaryAddValue(handlers, CFSTR("DownloadFile"), download_file);
CFDictionaryAddValue(handlers, CFSTR("AES"), remote_aes);
CFDictionaryAddValue(handlers, CFSTR("Reboot"), reboot__);
serve_plist_rpc(1999, handlers);
return 0;
}

View File

@@ -0,0 +1,14 @@
#!/bin/sh
if [ -a /dev/disk0s1s2 ]; then # test for iOS 5 data partition
mount_hfs /dev/disk0s1s1 /mnt1 2>/dev/null
mount_hfs /dev/disk0s1s2 /mnt2 2>/dev/null
elif [ -a /dev/disk0s2s1 ]; then # test for iOS 4 data partition
mount_hfs /dev/disk0s1 /mnt1 2>/dev/null
mount_hfs /dev/disk0s2s1 /mnt2 2>/dev/null
elif [ -a /dev/disk0s2 ]; then
mount_hfs /dev/disk0s1 /mnt1 2>/dev/null
mount_hfs /dev/disk0s2 /mnt2 2>/dev/null
else
echo "Error mounting partitions. Please try it manually"
fi

View File

@@ -0,0 +1,176 @@
#include <stdio.h>
#include <sys/types.h>
//#include <sys/mount.h>
//#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include "ioflash/ioflash.h"
#include "util.h"
struct IMG2
{
uint32_t magic;
uint32_t block_size;
uint32_t images_offset;
uint32_t images_block;
uint32_t images_length;
uint8_t padding[0x1c];
uint32_t crc32;
};
struct IMG3
{
uint32_t magic;
uint32_t fullSize;
uint32_t sizeNoPack;
uint32_t sigCheckArea;
uint32_t iden;
};
struct IMG3_TLV
{
uint32_t tag;
uint32_t total_length;
uint32_t data_length;
uint8_t payload[1];
};
void printIMG2(struct IMG2* s)
{
printf("magic= %x\n", s->magic);
printf("block_size= %x\n", s->block_size);
printf("images_offset= %x\n", s->images_offset);
printf("images_block= %x\n", s->images_block);
printf("images_length= %x\n", s->images_length);
}
void printIMG3(struct IMG3* s)
{
char iden[10]={0};
memcpy(iden, &s->iden, 4);
printf("magic= %x\n", s->magic);
printf("fullSize= %x\n", s->fullSize);
printf("iden= %s\n", iden);
}
CFDataRef getIMG3Data(struct IMG3* img3)
{
CFDataRef data = NULL;
uint8_t* p = (uint8_t*) img3;
uint8_t* z = &p[20];
if(img3->magic != 'Img3')
return NULL;
while(z < &p[img3->fullSize])
{
struct IMG3_TLV* item = (struct IMG3_TLV*) z;
if( item->tag == 'DATA')
{
data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, item->payload, item->data_length, NULL);
return data;
}
z += item->total_length;
}
return NULL;
}
extern uint32_t gPagesPerBlock;
extern uint32_t gBytesPerPage ;
extern uint32_t gBootloaderBytes ;
int main(int argc, char* argv[])
{
int one=1;
int cmd=0;
CFMutableDictionaryRef dict = FSDGetInfo(1);
if (dict == NULL)
{
fprintf(stderr, "FAILed to get NAND infos");
return -1;
}
if(!IOFlashStorage_kernel_patch())
return -1;
struct kIOFlashControllerOut out;
uint32_t bootSize = gBootloaderBytes * gPagesPerBlock * 8;
printf("Mallocing %x bytes for boot partition\n", bootSize);
uint8_t* boot = malloc(bootSize);
if( boot == NULL)
{
return -1;
}
uint8_t* buffer = malloc(gBytesPerPage);
if( buffer == NULL)
{
return -1;
}
uint32_t block, page, off=0;
for(block=8; block < 16; block++)
{
for(page=0; page < gPagesPerBlock; page++)
{
if(FSDReadBootPage(0, block*gPagesPerBlock + page, buffer, &out))
{
//printf("FSDReadBootPage error %x\n", block*gPagesPerBlock + page);
//return -1;
}
memcpy(&boot[off], buffer, gBootloaderBytes);
off += gBootloaderBytes;
}
}
printIMG2((struct IMG2*) boot);
struct IMG2* img2 = (struct IMG2*) boot;
if( img2->magic != 0x494d4732)
{
printf("Bag IMG2 magic : %x\n", img2->magic);
return -1;
}
uint32_t start = img2->block_size * img2->images_block;
uint32_t end = start + img2->block_size * img2->images_length;
if( end < start)
{
return -1;
}
printf("start %x end %x\n", start, end);
uint8_t* p = &boot[start];
CFMutableDictionaryRef resultsDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if(dict == NULL)
{
return -1;
}
while(p < &boot[end])
{
struct IMG3* img3 = (struct IMG3*) p;
if(img3->magic != 'Img3')
break;
printIMG3(img3);
if(img3->iden == 'SCAB')
{
CFDataRef data = getIMG3Data(img3);
if(data)
{
CFDictionaryAddValue(resultsDict, CFSTR("APTicket"), data);
writePlistToStdout(resultsDict);
CFRelease(data);
}
}
p += img3->fullSize;
}
return 0;
}

View File

@@ -0,0 +1,226 @@
#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 "image.h"
#include "remote_functions.h"
/*
#define MobileKeyBagBase 0x354cb000
CFDictionaryRef (*AppleKeyStore_loadKeyBag)(char*, char*) = MobileKeyBagBase + 0x50A8;
int (*AppleKeyStoreKeyBagSetSystem)(int) = MobileKeyBagBase + 0x910;
int (*AppleKeyStoreKeyBagCreateWithData)(CFDataRef, int*) = MobileKeyBagBase + 0xC88;
*/
/*
/private/var/mobile/Library/ConfigurationProfiles/PublicInfo/EffectiveUserSettings.plist.plist
plist["restrictedValue"]["passcodeKeyboardComplexity"]
*/
void saveKeybagInfos(CFDataRef kbkeys, KeyBag* kb, uint8_t* key835, char* passcode, uint8_t* passcodeKey, CFMutableDictionaryRef classKeys)
{
CFMutableDictionaryRef out = device_info(-1, NULL);
CFStringRef uuid = CreateHexaCFString(kb->uuid, 16);
CFDictionaryAddValue(out, CFSTR("uuid"), uuid);
CFDictionaryAddValue(out, CFSTR("KeyBagKeys"), kbkeys);
addHexaString(out, CFSTR("salt"), kb->salt, 20);
if (passcode != NULL)
{
CFStringRef cfpasscode = CFStringCreateWithCString(kCFAllocatorDefault, passcode, kCFStringEncodingASCII);
CFDictionaryAddValue(out, CFSTR("passcode"), cfpasscode);
CFRelease(cfpasscode);
}
if (passcodeKey != NULL)
addHexaString(out, CFSTR("passcodeKey"), passcodeKey, 32);
if (key835 != NULL)
addHexaString(out, CFSTR("key835"), key835, 16);
if (classKeys != NULL)
CFDictionaryAddValue(out, CFSTR("classKeys"), classKeys);
CFStringRef resultsFileName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@.plist"), CFDictionaryGetValue(out, CFSTR("dataVolumeUUID")));
CFStringRef printString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Writing results to %@.plist\n"), CFDictionaryGetValue(out, CFSTR("dataVolumeUUID")));
CFShow(printString);
CFRelease(printString);
saveResults(resultsFileName, out);
CFRelease(resultsFileName);
CFRelease(uuid);
CFRelease(out);
}
char* bruteforceWithAppleKeyStore(CFDataRef kbkeys)
{
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 (i % 1000 == 0)
printf("%s\n", passcode);
if (!AppleKeyStoreUnlockDevice(conn, data))
{
return passcode;
}
}
free(passcode);
return NULL;
}
char* bruteforceUserland(KeyBag* kb, uint8_t* key835)
{
int i;
char* passcode = (char*) malloc(5);
memset(passcode, 0, 5);
if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835))
return passcode;
for(i=0; i < 10000; i++)
{
sprintf(passcode, "%04d", i);
//if (i % 1000 == 0)
printf("%s\n", passcode);
if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835))
return passcode;
}
free(passcode);
return NULL;
}
int main(int argc, char* argv[])
{
u_int8_t passcodeKey[32]={0};
char* passcode = NULL;
int bruteforceMethod = 0;
int showImages = 0;
int c;
while ((c = getopt (argc, argv, "ui")) != -1)
{
switch (c)
{
case 'u':
bruteforceMethod = 1;
break;
case 'i':
showImages = 1;
break;
}
}
uint8_t* key835 = IOAES_key835();
if (!memcmp(key835, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
{
printf("FAIL: missing UID kernel patch\n");
return -1;
}
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 -1;
}
}
CFDataRef kbkeys = CFDictionaryGetValue(kbdict, CFSTR("KeyBagKeys"));
CFRetain(kbkeys);
if (kbkeys == NULL)
{
printf("FAIL: KeyBagKeys not found\n");
return -1;
}
//write_file("kbblob.bin", CFDataGetBytePtr(kbkeys), CFDataGetLength(kbkeys));
KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys);
if (kb == NULL)
{
printf("FAIL: AppleKeyStore_parseBinaryKeyBag\n");
return -1;
}
//save all we have for now
saveKeybagInfos(kbkeys, kb, key835, NULL, NULL, NULL);
//now try to unlock the keybag
if (bruteforceMethod == 1)
passcode = bruteforceUserland(kb, key835);
else
passcode = bruteforceWithAppleKeyStore(kbkeys);
if (passcode != NULL)
{
if (!strcmp(passcode, ""))
printf("No passcode set\n");
else
printf("Found passcode : %s\n", passcode);
AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835);
AppleKeyStore_printKeyBag(kb);
CFMutableDictionaryRef classKeys = AppleKeyStore_getClassKeys(kb);
AppleKeyStore_getPasscodeKey(kb, passcode, strlen(passcode), passcodeKey);
printf("Passcode key : ");
printBytesToHex(passcodeKey, 32);
printf("\n");
printf("Key 0x835 : ");
printBytesToHex(key835, 16);
printf("\n");
//save all we have for now
saveKeybagInfos(kbkeys, kb, key835, passcode, passcodeKey, classKeys);
CFRelease(classKeys);
free(passcode);
}
free(kb);
CFRelease(kbkeys);
CFRelease(kbdict);
return 0;
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>get-task-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,194 @@
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <CoreFoundation/CoreFoundation.h>
#include "util.h"
void printBytesToHex(const uint8_t* buffer, size_t bytes)
{
while(bytes > 0) {
printf("%02x", *buffer);
buffer++;
bytes--;
}
}
void printHexString(const char* description, const uint8_t* buffer, size_t bytes)
{
printf("%s : ", description);
printBytesToHex(buffer, bytes);
printf("\n");
}
int write_file(const char* filename, uint8_t* data, size_t len)
{
int fd = open(filename, O_CREAT | O_RDWR);
if (fd < 0)
return -1;
if (write(fd, data, len) != len)
return -1;
close(fd);
return 0;
}
void writePlistToStdout(CFDictionaryRef out)
{
CFDataRef d = CFPropertyListCreateData(kCFAllocatorDefault, out, kCFPropertyListXMLFormat_v1_0, 0, NULL);
if (d == NULL)
return;
write(1, CFDataGetBytePtr(d), CFDataGetLength(d));
}
int mountDataPartition(const char* mountpoint)
{
char* diskname = "/dev/disk0s2s1";
int err;
printf("Trying to mount data partition\n");
err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname);
if (!err)
return 0;
diskname = "/dev/disk0s1s2";
err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname);
if (!err)
return 0;
diskname = "/dev/disk0s2";
err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname);
return err;
}
int getHFSInfos(struct HFSInfos *infos)
{
char buf[8192] = {0};
struct HFSPlusVolumeHeader* header;
unsigned int i;
int fd = open("/dev/rdisk0s2", O_RDONLY);
if (fd < 0 )
fd = open("/dev/rdisk0s1s2", O_RDONLY); //ios5 lwvm
if (fd < 0 )
return fd;
lseek(fd, 0, SEEK_SET);
if (read(fd, buf, 8192) != 8192)
return -1;
close(fd);
header = (struct HFSPlusVolumeHeader*) &buf[0x400];
uint32_t blockSize = CFSwapInt32BigToHost(header->blockSize);
infos->volumeUUID = header->volumeUUID;
infos->blockSize = blockSize;
if (blockSize != 0x1000 && blockSize != 0x2000)
{
fprintf(stderr, "getHFSInfos: Unknown block size %x\n", blockSize);
}
else
{
fd = open("/dev/rdisk0", O_RDONLY);
if (fd < 0 )
return fd;
if (read(fd, buf, 8192) != 8192)
return -1;
if (!memcmp(buf, LwVMType, 16))
{
LwVM* lwvm = (LwVM*) buf;
if (lwvm->chunks[0] != 0xF000)
{
fprintf(stderr, "getHFSInfos: lwvm->chunks[0] != 0xF000\n");
return -1;
}
for(i=0; i < 0x400; i++)
{
if(lwvm->chunks[i] == 0x1000) //partition 1 block 0
{
break;
}
}
uint32_t LwVM_rangeShiftValue = 32 - __builtin_clz((lwvm->mediaSize - 1) >> 10);
infos->dataVolumeOffset = (i << LwVM_rangeShiftValue) / blockSize;
}
else
{
lseek(fd, 2*blockSize, SEEK_SET);
if (read(fd, buf, 8192) != 8192)
return -1;
close(fd);
infos->dataVolumeOffset = ((unsigned int*)buf)[0xA0/4];
}
}
return 0;
}
CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len)
{
int i;
CFMutableStringRef s = CFStringCreateMutable(kCFAllocatorDefault, len*2);
for(i=0; i < len; i++)
{
CFStringAppendFormat(s, NULL, CFSTR("%02x"), buffer[i]);
}
return s;
}
void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len)
{
CFMutableStringRef s = CreateHexaCFString(buffer, len);
CFDictionaryAddValue(out, key, s);
CFRelease(s);
}
void saveResults(CFStringRef filename, CFMutableDictionaryRef out)
{
CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL, filename, kCFURLPOSIXPathStyle, FALSE);
CFWriteStreamRef stream = CFWriteStreamCreateWithFile( NULL, fileURL);
CFWriteStreamOpen(stream);
CFPropertyListWriteToStream(out, stream, kCFPropertyListXMLFormat_v1_0, NULL);
CFWriteStreamClose(stream);
CFRelease(stream);
CFRelease(fileURL);
}
int create_listening_socket(int port)
{
struct sockaddr_in listen_addr;
int s, one = 1;
memset(&listen_addr, 0, sizeof(struct sockaddr));
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = htons(port);
listen_addr.sin_addr.s_addr = INADDR_ANY;
s = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (bind(s, (struct sockaddr *)&listen_addr, sizeof(struct sockaddr)) < 0)
{
perror("bind");
return -1;
}
listen(s, 10);
return s;
}

View File

@@ -0,0 +1,81 @@
struct HFSInfos {
uint64_t volumeUUID;
uint32_t blockSize;
uint32_t dataVolumeOffset;
};
struct HFSPlusVolumeHeader {
uint16_t signature;
uint16_t version;
uint32_t attributes;
uint32_t lastMountedVersion;
uint32_t journalInfoBlock;
uint32_t createDate;
uint32_t modifyDate;
uint32_t backupDate;
uint32_t checkedDate;
uint32_t fileCount;
uint32_t folderCount;
uint32_t blockSize;
uint32_t totalBlocks;
uint32_t freeBlocks;
uint32_t nextAllocation;
uint32_t rsrcClumpSize;
uint32_t dataClumpSize;
uint32_t nextCatalogID;
uint32_t writeCount;
uint64_t encodingsBitmap;
uint32_t finderInfo[6];
uint64_t volumeUUID;
/*
HFSPlusForkData allocationFile;
HFSPlusForkData extentsFile;
HFSPlusForkData catalogFile;
HFSPlusForkData attributesFile;
HFSPlusForkData startupFile;*/
} __attribute__((packed));
//https://github.com/iDroid-Project/openiBoot/blob/master/openiboot/includes/bdev.h
typedef struct _LwVMPartitionRecord {
uint64_t type[2];
uint64_t guid[2];
uint64_t begin;
uint64_t end;
uint64_t attribute; // 0 == unencrypted; 0x1000000000000 == encrypted
char partitionName[0x48];
} __attribute__ ((packed)) LwVMPartitionRecord;
typedef struct _LwVM {
uint64_t type[2];
uint64_t guid[2];
uint64_t mediaSize;
uint32_t numPartitions;
uint32_t crc32;
uint8_t unkn[464];
LwVMPartitionRecord partitions[12];
uint16_t chunks[1024]; // chunks[0] should be 0xF000
} __attribute__ ((packed)) LwVM;
static const char LwVMType[] = { 0x6A, 0x90, 0x88, 0xCF, 0x8A, 0xFD, 0x63, 0x0A, 0xE3, 0x51, 0xE2, 0x48, 0x87, 0xE0, 0xB9, 0x8B };
int getHFSInfos(struct HFSInfos *infos);
CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len);
void printBytesToHex(const uint8_t* buffer, size_t bytes);
void printHexString(const char* description, const uint8_t* buffer, size_t bytes);
int write_file(const char* filename, uint8_t* data, size_t len);
void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len);
void saveResults(CFStringRef filename, CFMutableDictionaryRef out);
void writePlistToStdout(CFDictionaryRef out);
int mountDataPartition(const char* mountpoint);
int create_listening_socket(int port);