def Decryption(self): dict = {} for type, data in tlvs(self.fbuf[KEYBAG_DATA_SIZE+KEYBAG_HEADER_SIZE:self.endofdata]): #if type == 'UUID': #print '%s : %s'%(type, uuid.UUID(bytes=data) ) if type == 'CLAS': #print ' [-] %s : %s'%(type, get_class_name(int(hexlify(data), 16) )) dict['CLAS'] = int(hexlify(data), 16) elif type == 'WRAP': #print '%s : %s'%(type, get_wrap_name(int(hexlify(data), 16) )) dict['WRAP'] = int(hexlify(data), 16) #elif type == 'KTYP': #print '%s : %s'%(type, get_key_type(int(hexlify(data), 16) )) elif type == 'WPKY': decryptedkey = '' if dict['WRAP'] == 1: decryptedkey = AESdecryptCBC(data, self.devicekey) #print ' [-] Decrypted Key : %s'%hexlify(decryptedkey) elif dict['WRAP'] == 3: try: unwrapped = aes_unwrap_key(self.passcodekey, data) except ValueError: print '[!] Invalid Password. Enter the valid user password' sys.exit() decryptedkey = AESdecryptCBC(unwrapped, self.devicekey) #print ' [-] Decrypted Key : %s'%hexlify(decryptedkey) self.keyring[dict['CLAS']] = decryptedkey # Key
def device_key_validation(self): if self.devicekey == '': return False if self.keybag['sign']: hmackey = aes_unwrap_key(self.devicekey, unhexlify(self.keybag['hmck'])) sigcheck = hmac.new(key=hmackey, msg=self.keybag['data'], digestmod=sha1).digest() if hexlify(sigcheck) != self.keybag['sign']: return False else: return False return True
def main(): parser = argparse.ArgumentParser(description='Tool for iCloud Keychain Analysis by @n0fate') parser.add_argument('-p', '--path', nargs=1, help='iCloud Keychain Path(~/Library/Keychains/[UUID]/)', required=True) parser.add_argument('-k', '--key', nargs=1, help='User Password', required=True) parser.add_argument('-x', '--exportfile', nargs=1, help='Write a decrypted contents to SQLite file (optional)', required=False) args = parser.parse_args() Pathoficloudkeychain = args.path[0] if os.path.isdir(Pathoficloudkeychain) is False: print '[!] Path is not directory' parser.print_help() sys.exit() if os.path.exists(Pathoficloudkeychain) is False: print '[!] Path is not exists' parser.print_help() sys.exit() export = 0 if args.exportfile is not None: if os.path.exists(args.exportfile[0]): print '[*] Export DB File is exists.' sys.exit() export = 1 # Start to analysis print 'Tool for iCloud Keychain Analysis by @n0fate' MachineUUID = os.path.basename(os.path.normpath(Pathoficloudkeychain)) PathofKeybag = os.path.join(Pathoficloudkeychain, 'user.kb') PathofKeychain = os.path.join(Pathoficloudkeychain, 'keychain-2.db') print '[*] UUID : %s'%MachineUUID print '[*] Keybag : %s'%PathofKeybag print '[*] iCloud Keychain File : %s'%PathofKeychain if os.path.exists(PathofKeybag) is False or os.path.exists(PathofKeychain) is False: print '[!] Can not found KeyBag or iCloud Keychain File' sys.exit() keybag = Keybag(PathofKeybag) keybag.load_keybag_header() keybag.debug_print_header() devicekey = keybag.device_key_init(uuid.UUID(MachineUUID).bytes) print '[*] The Device key : %s'%hexlify(devicekey) bresult = keybag.device_key_validation() if bresult == False: print '[!] Device Key validation : Failed. Maybe Invalid PlatformUUID' return else: print '[*] Device Key validation : Pass' passcodekey = keybag.generatepasscodekey(args.key[0]) print '[*] The passcode key : %s'%hexlify(passcodekey) keybag.Decryption() con = lite.connect(PathofKeychain) con.text_factory = str cur = con.cursor() tablelist = ['genp', 'inet', 'cert', 'keys'] if export: # Create DB exportDB = ExporySQLiteDB() exportDB.createDB(args.exportfile[0]) print '[*] Export DB Name : %s'%args.exportfile[0] for tablename in tablelist: if export is not 1: print '[+] Table Name : %s'%GetTableFullName(tablename) try: cur.execute("SELECT data FROM %s"%tablename) except lite.OperationalError: continue if export: # Get Table Schema sql = con.execute("pragma table_info('%s')"%tablename).fetchall() # Create a table exportDB.createTable(tablename, sql) for data, in cur: encblobheader = _memcpy(data[:sizeof(_EncryptedBlobHeader)], _EncryptedBlobHeader) encblobheader.clas &= 0x0F wrappedkey = data[sizeof(_EncryptedBlobHeader):sizeof(_EncryptedBlobHeader)+encblobheader.length] encrypted_data = data[sizeof(_EncryptedBlobHeader)+encblobheader.length:-16] key = keybag.GetKeybyClass(encblobheader.clas) if key == '': print '[!] Could not found any key at %d'%encblobheader.clas continue unwrappedkey = aes_unwrap_key(key, wrappedkey) decrypted = gcm_decrypt(unwrappedkey, "", encrypted_data, "", data[-16:]) if len(decrypted) is 0: continue if export is 0: print '[+] DECRYPTED INFO' blobparse = BlobParser() record = blobparse.ParseIt(decrypted, tablename, export) if export is 0: for k, v in record.items(): if k == 'Data': print ' [-]', k hexdump(v) elif k == 'Type' and GetTableFullName(tablename) == 'Keys': print ' [-]', k, ':', blobparse.GetKeyType(int(v)) else: print ' [-]', k, ':', v print '' else: # export is 1 record_lst = [] for k, v in record.items(): record_lst.append([k,v]) exportDB.insertData(tablename, record_lst) if export: exportDB.commit() exportDB.close() cur.close() con.close()