Un certain nombre d'utilisateurs d'iPhone malheureux m'ont demandé de les aider à restaurer les données de leurs sauvegardes iTunes. C'est facile lorsqu'ils ne sont pas chiffrés, mais pas lorsqu'ils sont chiffrés, que le mot de passe soit connu ou non.
En tant que tel, j'essaie de comprendre le schéma de cryptage utilisé sur les fichiers mddata et mdinfo lorsqu'ils sont cryptés. Sinon, je n'ai aucun problème à lire ces fichiers et j'ai construit des bibliothèques C # robustes pour le faire. (Si vous pouvez aider, je me fiche de la langue que vous utilisez. C'est le principe que je recherche ici!)
Le «Guide de déploiement Apple iPhone OS Enterprise» indique que «Les sauvegardes de périphérique peuvent être stockées au format crypté en sélectionnant l'option Crypter la sauvegarde iPhone dans le volet de résumé de périphérique d'iTunes. Les fichiers sont cryptés à l'aide d'AES128 avec une clé de 256 bits. La clé est stocké en toute sécurité dans le trousseau de l'iPhone. "
C'est un assez bon indice, et il y a de bonnes informations ici sur Stackoverflow sur l' interopérabilité iPhone AES / Rijndael suggérant qu'une taille de clé de 128 et le mode CBC peuvent être utilisés.
En plus de toute autre obfuscation, une clé et un vecteur d'initialisation (IV) / sel sont nécessaires.
On pourrait supposer que la clé est une manipulation du «mot de passe de sauvegarde» que les utilisateurs sont invités à entrer par iTunes et transmis à « AppleMobileBackup.exe », remplis d'une manière dictée par CBC. Cependant, étant donné la référence au trousseau de l'iPhone, je me demande si le "mot de passe de sauvegarde" ne peut pas être utilisé comme mot de passe sur un certificat X509 ou une clé privée symétrique, et si le certificat ou la clé privée elle-même pourrait être utilisée comme clé. ( AES et le processus de chiffrement / déchiffrement d'iTunes sont symétriques.)
La perfusion intraveineuse est une autre affaire, et cela pourrait être plusieurs choses. C'est peut-être l'une des clés codées en dur dans iTunes ou dans les appareils eux-mêmes .
Bien que le commentaire d'Apple ci-dessus suggère que la clé est présente sur le trousseau de l'appareil, je pense que ce n'est pas si important. On peut restaurer une sauvegarde cryptée sur un appareil différent , ce qui suggère que toutes les informations pertinentes pour le décryptage sont présentes dans la sauvegarde et la configuration iTunes, et que tout ce qui se trouve uniquement sur l'appareil n'est pas pertinent et remplaçable dans ce contexte. Alors, où pourrait être la clé?
J'ai répertorié ci-dessous les chemins à partir d'une machine Windows, mais c'est beaucoup plus important quel que soit le système d'exploitation que nous utilisons.
Le fichier "\ appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml" contient une PList avec une entrée dict "Keychain". Le "\ programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist" contient un PList avec "DeviceCertificate", "HostCertificate" et "RootCertificate", qui semblent tous être des certificats X509 valides. Le même fichier semble également contenir des clés asymétriques "RootPrivateKey" et "HostPrivateKey" (ma lecture suggère que celles-ci pourraient être PKCS # 7-enveloppées). De plus, dans chaque sauvegarde, il y a des valeurs «AuthSignature» et «AuthData» dans le fichier Manifest.plist, bien que celles-ci semblent pivotées à mesure que chaque fichier est sauvegardé de manière incrémentielle, suggèrent qu'elles ne sont pas très utiles en tant que clé, à moins que quelque chose de vraiment tout à fait impliqué est en cours.
Il y a beaucoup de choses trompeuses suggérant qu'il est facile d'obtenir des données à partir de sauvegardes cryptées. Ce n'est pas le cas, et à ma connaissance, cela n'a pas été fait. Contournement ou désactivation le cryptage de sauvegarde est une tout autre affaire, et ce n'est pas ce que je cherche à faire.
Il ne s'agit pas de pirater l'iPhone ou quoi que ce soit du genre. Tout ce que je cherche ici, c'est un moyen d'extraire des données (photos, contacts, etc.) à partir de sauvegardes iTunes cryptées, comme je peux en extraire des sauvegardes non cryptées. J'ai essayé toutes sortes de permutations avec les informations que j'ai mises ci-dessus mais je n'ai rien trouvé. J'apprécierais toute pensée ou technique que j'aurais pu manquer.
la source
Réponses:
Les chercheurs en sécurité Jean-Baptiste Bédrune et Jean Sigwald ont présenté comment procéder à Hack-in-the-box Amsterdam 2011 .
Depuis lors, Apple a publié un livre blanc sur la sécurité iOS avec plus de détails sur les clés et les algorithmes, et Charlie Miller et al. ont publié le manuel du pirate informatique iOS , qui couvre une partie du même terrain de manière pratique. Lorsque iOS 10 est sorti pour la première fois, il y a eu des changements dans le format de sauvegarde qu'Apple n'a pas annoncé au début, mais diverses personnes ont procédé à une ingénierie inverse des changements de format .
Les sauvegardes chiffrées sont excellentes
L'avantage des sauvegardes iPhone cryptées est qu'elles contiennent des éléments tels que des mots de passe WiFi qui ne sont pas dans les sauvegardes non cryptées régulières. Comme indiqué dans le livre blanc sur la sécurité iOS , les sauvegardes chiffrées sont considérées comme plus «sécurisées», c'est pourquoi Apple considère qu'il est normal d'y inclure des informations plus sensibles.
Un avertissement important: évidemment, décrypter la sauvegarde de votre appareil iOS supprime son cryptage. Pour protéger votre confidentialité et votre sécurité, vous ne devez exécuter ces scripts que sur une machine avec un chiffrement complet du disque.Bien qu'il soit possible pour un expert en sécurité d'écrire un logiciel qui protège les clés en mémoire, par exemple en utilisant des fonctions telles que
VirtualLock()
etSecureZeroMemory()
entre autres choses, ces scripts Python stockeront vos clés de chiffrement et vos mots de passe dans des chaînes à récupérer par Python. Cela signifie que vos clés secrètes et vos mots de passe vivront dans la RAM pendant un certain temps, d'où ils s'infiltreront dans votre fichier d'échange et sur votre disque, où un adversaire pourra les récupérer. Cela va complètement à l'encontre de l'intérêt d'avoir une sauvegarde cryptée.Comment décrypter les sauvegardes: en théorie
le livre blanc sur la sécurité iOS livre blanc sur la explique mieux que moi les concepts fondamentaux des clés par fichier, des classes de protection, des clés de classe de protection et des trousseaux de clés. Si vous ne les connaissez pas déjà, prenez quelques minutes pour lire les parties pertinentes.
Vous savez maintenant que chaque fichier dans iOS est chiffré avec sa propre clé de chiffrement aléatoire par fichier, appartient à une classe de protection et que les clés de chiffrement par fichier sont stockées dans les métadonnées du système de fichiers, enveloppées dans la clé de classe de protection.
Pour décrypter:
Décodez le keybag stocké dans l'
BackupKeyBag
entrée deManifest.plist
. Une vue d'ensemble de cette structure est donnée dans le livre blanc . Le Wiki iPhone décrit le format binaire: un champ de type chaîne de 4 octets, un champ de longueur big-endian de 4 octets, puis la valeur elle-même.Les valeurs importantes sont les
ITER
ations PBKDF2 etSALT
, le sel de double protectionDPSL
et le nombre d'itérationsDPIC
, puis pour chaque protectionCLS
, leWPKY
clé encapsulée.À l'aide du mot de passe de sauvegarde, dérivez une clé de 32 octets en utilisant le sel PBKDF2 correct et le nombre d'itérations. Utilisez d'abord un tour SHA256 avec
DPSL
etDPIC
, puis un tour SHA1 avecITER
etSALT
.Déballez chaque clé emballée conformément à la RFC 3394 .
Décryptez la base de données du manifeste en extrayant la classe de protection de 4 octets et la clé la plus longue de
ManifestKey
inManifest.plist
, et en la déballant. Vous disposez maintenant d'une base de données SQLite avec toutes les métadonnées de fichier.Pour chaque fichier d'intérêt, obtenez la clé de chiffrement par fichier et le code de classe de protection chiffrés par classe en recherchant dans la
Files.file
colonne de la base de données un fichier binaire contenant les entréesEncryptionKey
etProtectionClass
. Supprimez la balise de longueur initiale de quatre octetsEncryptionKey
avant de l'utiliser.Ensuite, dérivez la clé de décryptage finale en la déballant avec la clé de classe qui a été déballée avec le mot de passe de sauvegarde. Décryptez ensuite le fichier en utilisant AES en mode CBC avec un zéro IV.
Comment décrypter les sauvegardes: en pratique
Vous aurez d'abord besoin de quelques dépendances de bibliothèque. Si vous êtes sur un mac utilisant un Python 2.7 ou 3.7 installé par homebrew, vous pouvez installer les dépendances avec:
CFLAGS="-I$(brew --prefix)/opt/openssl/include" \ LDFLAGS="-L$(brew --prefix)/opt/openssl/lib" \ pip install biplist fastpbkdf2 pycrypto
Sous forme de code source exécutable, voici comment décrypter un seul fichier de préférences à partir d'une sauvegarde iPhone cryptée:
#!/usr/bin/env python3.7 # coding: UTF-8 from __future__ import print_function from __future__ import division import argparse import getpass import os.path import pprint import random import shutil import sqlite3 import string import struct import tempfile from binascii import hexlify import Crypto.Cipher.AES # https://www.dlitz.net/software/pycrypto/ import biplist import fastpbkdf2 from biplist import InvalidPlistException def main(): ## Parse options parser = argparse.ArgumentParser() parser.add_argument('--backup-directory', dest='backup_directory', default='testdata/encrypted') parser.add_argument('--password-pipe', dest='password_pipe', help="""\ Keeps password from being visible in system process list. Typical use: --password-pipe=<(echo -n foo) """) parser.add_argument('--no-anonymize-output', dest='anonymize', action='store_false') args = parser.parse_args() global ANONYMIZE_OUTPUT ANONYMIZE_OUTPUT = args.anonymize if ANONYMIZE_OUTPUT: print('Warning: All output keys are FAKE to protect your privacy') manifest_file = os.path.join(args.backup_directory, 'Manifest.plist') with open(manifest_file, 'rb') as infile: manifest_plist = biplist.readPlist(infile) keybag = Keybag(manifest_plist['BackupKeyBag']) # the actual keys are unknown, but the wrapped keys are known keybag.printClassKeys() if args.password_pipe: password = readpipe(args.password_pipe) if password.endswith(b'\n'): password = password[:-1] else: password = getpass.getpass('Backup password: ').encode('utf-8') ## Unlock keybag with password if not keybag.unlockWithPasscode(password): raise Exception('Could not unlock keybag; bad password?') # now the keys are known too keybag.printClassKeys() ## Decrypt metadata DB manifest_key = manifest_plist['ManifestKey'][4:] with open(os.path.join(args.backup_directory, 'Manifest.db'), 'rb') as db: encrypted_db = db.read() manifest_class = struct.unpack('<l', manifest_plist['ManifestKey'][:4])[0] key = keybag.unwrapKeyForClass(manifest_class, manifest_key) decrypted_data = AESdecryptCBC(encrypted_db, key) temp_dir = tempfile.mkdtemp() try: # Does anyone know how to get Python’s SQLite module to open some # bytes in memory as a database? db_filename = os.path.join(temp_dir, 'db.sqlite3') with open(db_filename, 'wb') as db_file: db_file.write(decrypted_data) conn = sqlite3.connect(db_filename) conn.row_factory = sqlite3.Row c = conn.cursor() # c.execute("select * from Files limit 1"); # r = c.fetchone() c.execute(""" SELECT fileID, domain, relativePath, file FROM Files WHERE relativePath LIKE 'Media/PhotoData/MISC/DCIM_APPLE.plist' ORDER BY domain, relativePath""") results = c.fetchall() finally: shutil.rmtree(temp_dir) for item in results: fileID, domain, relativePath, file_bplist = item plist = biplist.readPlistFromString(file_bplist) file_data = plist['$objects'][plist['$top']['root'].integer] size = file_data['Size'] protection_class = file_data['ProtectionClass'] encryption_key = plist['$objects'][ file_data['EncryptionKey'].integer]['NS.data'][4:] backup_filename = os.path.join(args.backup_directory, fileID[:2], fileID) with open(backup_filename, 'rb') as infile: data = infile.read() key = keybag.unwrapKeyForClass(protection_class, encryption_key) # truncate to actual length, as encryption may introduce padding decrypted_data = AESdecryptCBC(data, key)[:size] print('== decrypted data:') print(wrap(decrypted_data)) print() print('== pretty-printed plist') pprint.pprint(biplist.readPlistFromString(decrypted_data)) ## # this section is mostly copied from parts of iphone-dataprotection # http://code.google.com/p/iphone-dataprotection/ CLASSKEY_TAGS = [b"CLAS",b"WRAP",b"WPKY", b"KTYP", b"PBKY"] #UUID KEYBAG_TYPES = ["System", "Backup", "Escrow", "OTA (icloud)"] KEY_TYPES = ["AES", "Curve25519"] PROTECTION_CLASSES={ 1:"NSFileProtectionComplete", 2:"NSFileProtectionCompleteUnlessOpen", 3:"NSFileProtectionCompleteUntilFirstUserAuthentication", 4:"NSFileProtectionNone", 5:"NSFileProtectionRecovery?", 6: "kSecAttrAccessibleWhenUnlocked", 7: "kSecAttrAccessibleAfterFirstUnlock", 8: "kSecAttrAccessibleAlways", 9: "kSecAttrAccessibleWhenUnlockedThisDeviceOnly", 10: "kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly", 11: "kSecAttrAccessibleAlwaysThisDeviceOnly" } WRAP_DEVICE = 1 WRAP_PASSCODE = 2 class Keybag(object): def __init__(self, data): self.type = None self.uuid = None self.wrap = None self.deviceKey = None self.attrs = {} self.classKeys = {} self.KeyBagKeys = None #DATASIGN blob self.parseBinaryBlob(data) def parseBinaryBlob(self, data): currentClassKey = None for tag, data in loopTLVBlocks(data): if len(data) == 4: data = struct.unpack(">L", data)[0] if tag == b"TYPE": self.type = data if self.type > 3: print("FAIL: keybag type > 3 : %d" % self.type) elif tag == b"UUID" and self.uuid is None: self.uuid = data elif tag == b"WRAP" and self.wrap is None: self.wrap = data elif tag == b"UUID": if currentClassKey: self.classKeys[currentClassKey[b"CLAS"]] = currentClassKey currentClassKey = {b"UUID": data} elif tag in CLASSKEY_TAGS: currentClassKey[tag] = data else: self.attrs[tag] = data if currentClassKey: self.classKeys[currentClassKey[b"CLAS"]] = currentClassKey def unlockWithPasscode(self, passcode): passcode1 = fastpbkdf2.pbkdf2_hmac('sha256', passcode, self.attrs[b"DPSL"], self.attrs[b"DPIC"], 32) passcode_key = fastpbkdf2.pbkdf2_hmac('sha1', passcode1, self.attrs[b"SALT"], self.attrs[b"ITER"], 32) print('== Passcode key') print(anonymize(hexlify(passcode_key))) for classkey in self.classKeys.values(): if b"WPKY" not in classkey: continue k = classkey[b"WPKY"] if classkey[b"WRAP"] & WRAP_PASSCODE: k = AESUnwrap(passcode_key, classkey[b"WPKY"]) if not k: return False classkey[b"KEY"] = k return True def unwrapKeyForClass(self, protection_class, persistent_key): ck = self.classKeys[protection_class][b"KEY"] if len(persistent_key) != 0x28: raise Exception("Invalid key length") return AESUnwrap(ck, persistent_key) def printClassKeys(self): print("== Keybag") print("Keybag type: %s keybag (%d)" % (KEYBAG_TYPES[self.type], self.type)) print("Keybag version: %d" % self.attrs[b"VERS"]) print("Keybag UUID: %s" % anonymize(hexlify(self.uuid))) print("-"*209) print("".join(["Class".ljust(53), "WRAP".ljust(5), "Type".ljust(11), "Key".ljust(65), "WPKY".ljust(65), "Public key"])) print("-"*208) for k, ck in self.classKeys.items(): if k == 6:print("") print("".join( [PROTECTION_CLASSES.get(k).ljust(53), str(ck.get(b"WRAP","")).ljust(5), KEY_TYPES[ck.get(b"KTYP",0)].ljust(11), anonymize(hexlify(ck.get(b"KEY", b""))).ljust(65), anonymize(hexlify(ck.get(b"WPKY", b""))).ljust(65), ])) print() def loopTLVBlocks(blob): i = 0 while i + 8 <= len(blob): tag = blob[i:i+4] length = struct.unpack(">L",blob[i+4:i+8])[0] data = blob[i+8:i+8+length] yield (tag,data) i += 8 + length def unpack64bit(s): return struct.unpack(">Q",s)[0] def pack64bit(s): return struct.pack(">Q",s) def AESUnwrap(kek, wrapped): C = [] for i in range(len(wrapped)//8): C.append(unpack64bit(wrapped[i*8:i*8+8])) n = len(C) - 1 R = [0] * (n+1) A = C[0] for i in range(1,n+1): R[i] = C[i] for j in reversed(range(0,6)): for i in reversed(range(1,n+1)): todec = pack64bit(A ^ (n*j+i)) todec += pack64bit(R[i]) B = Crypto.Cipher.AES.new(kek).decrypt(todec) A = unpack64bit(B[:8]) R[i] = unpack64bit(B[8:]) if A != 0xa6a6a6a6a6a6a6a6: return None res = b"".join(map(pack64bit, R[1:])) return res ZEROIV = "\x00"*16 def AESdecryptCBC(data, key, iv=ZEROIV, padding=False): if len(data) % 16: print("AESdecryptCBC: data length not /16, truncating") data = data[0:(len(data)/16) * 16] data = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, iv).decrypt(data) if padding: return removePadding(16, data) return data ## # here are some utility functions, one making sure I don’t leak my # secret keys when posting the output on Stack Exchange anon_random = random.Random(0) memo = {} def anonymize(s): if type(s) == str: s = s.encode('utf-8') global anon_random, memo if ANONYMIZE_OUTPUT: if s in memo: return memo[s] possible_alphabets = [ string.digits, string.digits + 'abcdef', string.ascii_letters, "".join(chr(x) for x in range(0, 256)), ] for a in possible_alphabets: if all((chr(c) if type(c) == int else c) in a for c in s): alphabet = a break ret = "".join([anon_random.choice(alphabet) for i in range(len(s))]) memo[s] = ret return ret else: return s def wrap(s, width=78): "Return a width-wrapped repr(s)-like string without breaking on \’s" s = repr(s) quote = s[0] s = s[1:-1] ret = [] while len(s): i = s.rfind('\\', 0, width) if i <= width - 4: # "\x??" is four characters i = width ret.append(s[:i]) s = s[i:] return '\n'.join("%s%s%s" % (quote, line ,quote) for line in ret) def readpipe(path): if stat.S_ISFIFO(os.stat(path).st_mode): with open(path, 'rb') as pipe: return pipe.read() else: raise Exception("Not a pipe: {!r}".format(path)) if __name__ == '__main__': main()
Qui imprime ensuite cette sortie:
Warning: All output keys are FAKE to protect your privacy == Keybag Keybag type: Backup keybag (1) Keybag version: 3 Keybag UUID: dc6486c479e84c94efce4bea7169ef7d ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Class WRAP Type Key WPKY Public key ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- NSFileProtectionComplete 2 AES 4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceedee86b4cde9f97afec197ad3b13c5d12b NSFileProtectionCompleteUnlessOpen 2 AES 09e8a0a9965f00f213ce06143a52801f35bde2af0ad54972769845d480b5043f545fa9b66a0353a6 NSFileProtectionCompleteUntilFirstUserAuthentication 2 AES e966b6a0742878ce747cec3fa1bf6a53b0d811ad4f1d6147cd28a5d400a8ffe0bbabea5839025cb5 NSFileProtectionNone 2 AES 902f46847302816561e7df57b64beea6fa11b0068779a65f4c651dbe7a1630f323682ff26ae7e577 NSFileProtectionRecovery? 3 AES a3935fed024cd9bc11d0300d522af8e89accfbe389d7c69dca02841df46c0a24d0067dba2f696072 kSecAttrAccessibleWhenUnlocked 2 AES 09a1856c7e97a51a9c2ecedac8c3c7c7c10e7efa931decb64169ee61cb07a0efb115050fd1e33af1 kSecAttrAccessibleAfterFirstUnlock 2 AES 0509d215f2f574efa2f192efc53c460201168b26a175f066b5347fc48bc76c637e27a730b904ca82 kSecAttrAccessibleAlways 2 AES b7ac3c4f1e04896144ce90c4583e26489a86a6cc45a2b692a5767b5a04b0907e081daba009fdbb3c kSecAttrAccessibleWhenUnlockedThisDeviceOnly 3 AES 417526e67b82e7c6c633f9063120a299b84e57a8ffee97b34020a2caf6e751ec5750053833ab4d45 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 3 AES b0e17b0cf7111c6e716cd0272de5684834798431c1b34bab8d1a1b5aba3d38a3a42c859026f81ccc kSecAttrAccessibleAlwaysThisDeviceOnly 3 AES 9b3bdc59ae1d85703aa7f75d49bdc600bf57ba4a458b20a003a10f6e36525fb6648ba70e6602d8b2 == Passcode key ee34f5bb635830d698074b1e3e268059c590973b0f1138f1954a2a4e1069e612 == Keybag Keybag type: Backup keybag (1) Keybag version: 3 Keybag UUID: dc6486c479e84c94efce4bea7169ef7d ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Class WRAP Type Key WPKY Public key ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- NSFileProtectionComplete 2 AES 64e8fc94a7b670b0a9c4a385ff395fe9ba5ee5b0d9f5a5c9f0202ef7fdcb386f 4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceedee86b4cde9f97afec197ad3b13c5d12b NSFileProtectionCompleteUnlessOpen 2 AES 22a218c9c446fbf88f3ccdc2ae95f869c308faaa7b3e4fe17b78cbf2eeaf4ec9 09e8a0a9965f00f213ce06143a52801f35bde2af0ad54972769845d480b5043f545fa9b66a0353a6 NSFileProtectionCompleteUntilFirstUserAuthentication 2 AES 1004c6ca6e07d2b507809503180edf5efc4a9640227ac0d08baf5918d34b44ef e966b6a0742878ce747cec3fa1bf6a53b0d811ad4f1d6147cd28a5d400a8ffe0bbabea5839025cb5 NSFileProtectionNone 2 AES 2e809a0cd1a73725a788d5d1657d8fd150b0e360460cb5d105eca9c60c365152 902f46847302816561e7df57b64beea6fa11b0068779a65f4c651dbe7a1630f323682ff26ae7e577 NSFileProtectionRecovery? 3 AES 9a078d710dcd4a1d5f70ea4062822ea3e9f7ea034233e7e290e06cf0d80c19ca a3935fed024cd9bc11d0300d522af8e89accfbe389d7c69dca02841df46c0a24d0067dba2f696072 kSecAttrAccessibleWhenUnlocked 2 AES 606e5328816af66736a69dfe5097305cf1e0b06d6eb92569f48e5acac3f294a4 09a1856c7e97a51a9c2ecedac8c3c7c7c10e7efa931decb64169ee61cb07a0efb115050fd1e33af1 kSecAttrAccessibleAfterFirstUnlock 2 AES 6a4b5292661bac882338d5ebb51fd6de585befb4ef5f8ffda209be8ba3af1b96 0509d215f2f574efa2f192efc53c460201168b26a175f066b5347fc48bc76c637e27a730b904ca82 kSecAttrAccessibleAlways 2 AES c0ed717947ce8d1de2dde893b6026e9ee1958771d7a7282dd2116f84312c2dd2 b7ac3c4f1e04896144ce90c4583e26489a86a6cc45a2b692a5767b5a04b0907e081daba009fdbb3c kSecAttrAccessibleWhenUnlockedThisDeviceOnly 3 AES 80d8c7be8d5103d437f8519356c3eb7e562c687a5e656cfd747532f71668ff99 417526e67b82e7c6c633f9063120a299b84e57a8ffee97b34020a2caf6e751ec5750053833ab4d45 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 3 AES a875a15e3ff901351c5306019e3b30ed123e6c66c949bdaa91fb4b9a69a3811e b0e17b0cf7111c6e716cd0272de5684834798431c1b34bab8d1a1b5aba3d38a3a42c859026f81ccc kSecAttrAccessibleAlwaysThisDeviceOnly 3 AES 1e7756695d337e0b06c764734a9ef8148af20dcc7a636ccfea8b2eb96a9e9373 9b3bdc59ae1d85703aa7f75d49bdc600bf57ba4a458b20a003a10f6e36525fb6648ba70e6602d8b2 == decrypted data: '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD ' 'PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist versi' 'on="1.0">\n<dict>\n\t<key>DCIMLastDirectoryNumber</key>\n\t<integer>100</integ' 'er>\n\t<key>DCIMLastFileNumber</key>\n\t<integer>3</integer>\n</dict>\n</plist' '>\n' == pretty-printed plist {'DCIMLastDirectoryNumber': 100, 'DCIMLastFileNumber': 3}
Crédit supplémentaire
Le code de protection des données iphone publié par Bédrune et Sigwald peut décrypter le trousseau à partir d'une sauvegarde, y compris des choses amusantes comme le wifi enregistré et les mots de passe du site Web:
Ce code ne fonctionne plus sur les sauvegardes à partir de téléphones utilisant le dernier iOS, mais certains ports Golang ont été maintenus à jour permettant l'accès au trousseau .
la source
pip install --user pycrypto
Merci!Désolé, mais cela pourrait même être plus compliqué, impliquant pbkdf2, ou même une variante de celui-ci. Écoutez la session # 209 de la WWDC 2010, qui parle principalement des mesures de sécurité dans iOS 4, mais mentionne également brièvement le chiffrement séparé des sauvegardes et leur relation.
Vous pouvez être à peu près sûr que sans connaître le mot de passe, vous ne pouvez pas le déchiffrer, même par force brute.
Supposons simplement que vous souhaitiez permettre aux personnes qui CONNAISSENT le mot de passe d'accéder aux données de leurs sauvegardes.
Je crains qu'il n'y ait aucun moyen de regarder le code réel dans iTunes afin de déterminer quels algos sont utilisés.
À l'époque de Newton, je devais déchiffrer les données d'un programme et pouvais appeler sa fonction de déchiffrement directement (connaissant le mot de passe, bien sûr) sans même avoir besoin de comprendre son algorithme. Ce n'est plus aussi simple, malheureusement.
Je suis sûr qu'il y a des gens qualifiés qui pourraient faire de l'ingénierie inverse sur ce code iTunes - il suffit de les intéresser.
En théorie, les algos d'Apple devraient être conçus de manière à rendre les données encore sûres (c'est-à-dire pratiquement incassables par les méthodes de force brute) pour tout attaquant connaissant la méthode de cryptage exacte. Et lors de la session 209 de la WWDC, ils sont allés assez loin dans les détails de ce qu'ils font pour y parvenir. Peut-être que vous pouvez obtenir des réponses directement de l'équipe de sécurité d'Apple si vous leur dites vos bonnes intentions. Après tout, même eux doivent savoir que la sécurité par obfuscation n'est pas vraiment efficace. Essayez leur liste de diffusion de sécurité. Même s'ils ne répondent pas, peut-être que quelqu'un d'autre sur la liste répondra en silence avec de l'aide.
Bonne chance!
la source
Je ne l'ai pas essayé, mais Elcomsoft a publié un produit qui, selon lui, est capable de décrypter les sauvegardes, à des fins médico-légales. Peut-être pas aussi cool que de concevoir une solution vous-même, mais cela pourrait être plus rapide.
http://www.elcomsoft.com/eppb.html
la source
Vous devriez récupérer une copie de l'utilitaire de ligne de commande mdhelper d'Erica Sadun ( binaire et source OS X ). Il prend en charge la liste et l'extraction du contenu des sauvegardes iPhone / iPod Touch, y compris le carnet d'adresses et les bases de données SMS, ainsi que d'autres métadonnées et paramètres d'application.
la source