89 votes

Comment décrypter une sauvegarde Apple iTunes iPhone cryptée ?

Un certain nombre d'utilisateurs malheureux d'iPhone m'ont demandé de les aider à restaurer des données à partir de leurs sauvegardes iTunes. C'est facile lorsqu'elles sont non cryptées, mais pas lorsqu'elles sont cryptées, 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. Je n'ai aucun problème à lire ces fichiers autrement, et j'ai construit quelques bibliothèques C# robustes pour le faire. (Si vous êtes en mesure d'aider, je ne me soucie pas du langage que vous utilisez. C'est le principe qui m'intéresse ici).

Le "iPhone OS Enterprise Deployment Guide" d'Apple indique que "les sauvegardes de l'appareil peuvent être stockées en format crypté en sélectionnant l'option Encrypt iPhone dans le panneau de résumé de l'appareil dans iTunes. Les fichiers sont chiffrés à l'aide du protocole AES128 avec une clé de 256 bits. La clé est stockée de manière sécurisée dans le trousseau de l'iPhone."

C'est un bon indice, et il y a de bonnes informations sur l'iPhone ici sur Stackoverflow. Interopérabilité AES/Rijndael suggérant une taille de clé de 128 et le mode CBC peut être utilisé.

En dehors de toute autre obfuscation, une clé et un vecteur d'initialisation (IV)/salt sont nécessaires.

On peut supposer que la clé est une manipulation du "mot de passe de sauvegarde" que les utilisateurs sont invités à saisir par iTunes et qui est transmis à " AppleMobileBackup.exe ", rembourré d'une manière dictée par la CBC. Cependant, étant donné la référence au trousseau de l'iPhone, je me demande si le "mot de passe de secours" ne pourrait pas être utilisé comme mot de passe sur un certificat X509 ou une clé privée symétrique, et que le certificat ou la clé privée lui-même pourrait être utilisé comme clé. ( AES et le processus de cryptage/décryptage d'iTunes est symétrique).

L'IV est une autre question, et cela pourrait être plusieurs choses. Peut-être que c'est l'une des clés codé en dur dans iTunes, ou dans le les dispositifs 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 trousseau de clés. différents ce qui suggère que toutes les informations pertinentes pour le décryptage sont présentes dans la sauvegarde et la configuration d'iTunes, et que tout ce qui se trouve uniquement sur l'appareil n'est pas pertinent et peut être remplacé dans ce contexte. Alors, où pourrait se trouver la clé ?

J'ai listé les chemins d'accès ci-dessous à partir d'une machine Windows, mais c'est un peu la même chose quel que soit le système d'exploitation utilisé.

Le " \appdata\Roaming\Apple Ordinateur \iTunes\itunesprefs.xml "contient une PList avec une entrée de dictée "Keychain". Le " \programdata\apple\Lockdown\09037027da8f4bdefdea97d706703ca034c88bab.plist "contient une 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" (mes lectures suggèrent que celles-ci pourraient être développées en PKCS #7). De plus, dans chaque sauvegarde, il y a des valeurs "AuthSignature" et "AuthData" dans le fichier Manifest.plist, bien qu'elles semblent faire l'objet d'une rotation lorsque chaque fichier est sauvegardé de manière incrémentielle, ce qui suggère qu'elles ne sont pas très utiles en tant que clé, à moins que quelque chose de vraiment très impliqué ne soit fait.

Il existe de nombreuses informations trompeuses suggérant qu'il est facile d'extraire des données de sauvegardes cryptées. Ce n'est pas le cas, et à ma connaissance, cela n'a jamais été fait. Contournement ou désactivation le cryptage de la sauvegarde est une toute autre affaire, et ce n'est pas ce que je cherche à faire.

Il ne s'agit pas de pirater l'iPhone ou quelque chose comme ça. Tout ce que je cherche ici, c'est un moyen d'extraire des données (photos, contacts, etc.) de sauvegardes iTunes cryptées comme je peux le faire de sauvegardes non cryptées. J'ai essayé toutes sortes de permutations avec les informations que j'ai écrites ci-dessus mais je n'ai rien trouvé. J'apprécierais toute réflexion ou technique que j'aurais pu manquer.

3 votes

Mise à jour trois ans plus tard : J'ai trouvé une solution et l'ai transformée en un produit disponible gratuitement. J'étais sur la bonne voie ci-dessus, mais c'était difficile.

0 votes

Avez-vous un lien pour ce produit ?

1 votes

Comme vous l'avez demandé, c'est le Extracteur de sauvegarde pour iPhone . Vous verrez qu'il existe des éditions payantes du programme, mais la bonne vieille édition gratuite vous permettra d'extraire les fichiers cryptés 4 par 4.

113voto

andrewdotn Points 9183

Les chercheurs en sécurité Jean-Baptiste Bédrune et Jean Sigwald a présenté comment de faire cela sur Hack-in-the-box Amsterdam 2011 .

Depuis lors, Apple a publié une Livre blanc sur la sécurité d'iOS avec plus de détails sur les clés et les algorithmes, et Charlie Miller et al. ont publié la Manuel du hacker iOS qui couvre une partie du même d'une manière didactique. Lorsque iOS 10 est sorti il y a eu des changements au format de sauvegarde qu'Apple n'a pas rendu public dans un premier temps, mais plusieurs personnes inversé les changements de format .

Les sauvegardes cryptées sont excellentes

Ce qui est bien avec les sauvegardes cryptées de l'iPhone, c'est qu'elles contiennent des choses comme les mots de passe WiFi qui ne sont pas dans les sauvegardes normales non cryptées. Comme discuté dans le Livre blanc sur la sécurité d'iOS les sauvegardes cryptées sont considérées comme plus "sûres", donc Apple considère qu'il est acceptable d'y inclure plus informations sensibles.

Un avertissement important : évidemment, le décryptage de la sauvegarde de votre appareil iOS supprime son chiffrement. Pour protéger votre vie privée et votre sécurité, vous devez exécuter ces scripts uniquement sur une machine avec un chiffrement complet du disque. Bien qu'il soit il est 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() et SecureZeroMemory() parmi beaucoup d'autres choses, ces scripts Python stockeront vos clés de chiffrement et vos mots de passe dans des chaînes qui seront être collectées par Python. Cela signifie que vos clés et mots de passe secrets secrets vivront dans la RAM pendant un certain temps, d'où ils fuiront dans votre fichier et sur votre disque, où un adversaire pourra les récupérer. Cette Cela va complètement à l'encontre de l'intérêt d'avoir une sauvegarde chiffrée.

Comment décrypter les sauvegardes : en théorie

El Livre blanc sur la sécurité d'iOS explique les concepts fondamentaux des clés par fichier, des classes de protection, des clés de classe de protection et des sacs à clés. mieux que moi. Si vous n'êtes pas déjà familiarisé avec ces notions, prenez quelques quelques minutes pour lire les parties concernées.

Maintenant vous savez que chaque fichier dans iOS est crypté avec son propre aléatoire. aléatoire par fichier, qu'il appartient à une classe de protection et que les clés de sont stockées dans les métadonnées du système de fichiers, enveloppées dans la balise clé de classe de protection.

Pour décrypter :

  1. Décoder le keybag stocké dans le BackupKeyBag l'entrée de Manifest.plist . Un aperçu de haut niveau de cette structure est donné dans le site livre blanc . Le site iPhone Wiki décrit le format binaire : un champ de type chaîne de 4 octets, un champ de longueur big-endian de 4 octets et la valeur elle-même. big-endian, puis la valeur elle-même.

    Les valeurs importantes sont le PBKDF2 ITER ations et SALT le double protection du sel DPSL et le nombre d'itérations DPIC et ensuite, pour chaque protection CLS le WPKY clé enveloppée.

  2. En utilisant le mot de passe de sauvegarde, dérivez une clé de 32 octets en utilisant le bon PBKDF2 et le nombre d'itérations. Utilisez d'abord un tour SHA256 avec DPSL et DPIC puis un cycle SHA1 avec ITER y SALT .

    Défaites chaque clé enveloppée selon RFC 3394 .

  3. 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 la base de données du manifeste. ManifestKey en Manifest.plist et le déballer. Vous avez maintenant une base de données SQLite avec toutes les métadonnées du fichier.

  4. Pour chaque fichier d'intérêt, obtenez la clé de chiffrement par fichier chiffré par classe et le code de classe de protection en regardant dans le fichier Files.file base de données pour une liste binaire contenant EncryptionKey et ProtectionClass entrées. Retirez la balise de longueur initiale de quatre octets de EncryptionKey avant de l'utiliser.

    Ensuite, obtenez la clé de décryptage finale en la déballant avec la classe qui a été déballée avec le mot de passe de sauvegarde. Ensuite, décryptez le fichier en utilisant AES en mode CBC avec un IV de zéro.

Comment décrypter les sauvegardes : en pratique

Tout d'abord, vous aurez besoin de quelques dépendances de bibliothèque. Si vous êtes sur un mac et que vous utilisez un Python 2.7 ou 3.7 installé en 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 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

El code de protection des données de l'iphone posté par Bédrune et Sigwald peut décrypter le porte-clés d'une sauvegarde, y compris les choses amusantes comme les mots de passe wifi et les mots de passe de sites web :

$ python iphone-dataprotection/python_scripts/keychain_tool.py ...

--------------------------------------------------------------------------------------
|                              Passwords                                             |
--------------------------------------------------------------------------------------
|Service           |Account          |Data           |Access group  |Protection class|
--------------------------------------------------------------------------------------
|AirPort           |Ed’s Coffee Shop |<3FrenchRoast  |apple         |AfterFirstUnlock|
...

Ce code ne fonctionne plus sur les sauvegardes de téléphones utilisant la dernière version d'iOS, mais il y a quelques golang ports qui ont été mises à jour permettant l'accès à la porte-clés .

2 votes

Je l'ai essayé et il a fonctionné là où tous les autres outils ont échoué. J'ai dû ajouter un autre module python manquant : pip install --user pycrypto Merci !

1 votes

Un poste incroyable ! Explication impressionnante. Merci.

2 votes

Merveilleux ! En utilisant macports j'ai installé ces dépendances : py27-m2crypto py27-cryptography

7voto

Thomas Tempelmann Points 2849

Désolé, mais cela pourrait même être plus compliqué, impliquant pbkdf2, ou même une variation de celui-ci. Écoutez la session #209 de la WWDC 2010, qui parle principalement des mesures de sécurité dans iOS 4, mais mentionne aussi brièvement le cryptage séparé des sauvegardes et comment ils sont liés.

Vous pouvez être sûr que sans connaître le mot de passe, il n'y a aucun moyen de le décrypter, même par force brute.

Supposons que vous vouliez essayer de permettre aux personnes qui SAISISSENT le mot de passe d'accéder aux données de leurs sauvegardes.

Je crains qu'il n'y ait pas d'autre moyen que de regarder le code réel d'iTunes pour savoir quels algorithmes sont utilisés.

À l'époque de Newton, je devais décrypter les données d'un programme et j'étais capable d'appeler directement sa fonction de décryptage (en connaissant le mot de passe, bien sûr) sans même avoir besoin de comprendre son algorithme. Ce n'est plus aussi facile aujourd'hui, malheureusement.

Je suis sûr qu'il y a des gens compétents qui pourraient désosser ce code iTunes - il faut juste les intéresser.

En théorie, les algorithmes d'Apple devraient être conçus de manière à ce que les données soient toujours sûres (c'est-à-dire pratiquement inviolables par des méthodes de force brute) pour tout attaquant connaissant la méthode de cryptage exacte. Lors de la session 209 de la WWDC, ils ont expliqué en détail ce qu'ils font pour y parvenir. Peut-être pouvez-vous obtenir des réponses directement de l'équipe de sécurité d'Apple si vous leur faites part de vos bonnes intentions. Après tout, même eux devraient savoir que la sécurité par obscurcissement n'est pas vraiment efficace. Essayez leur liste de diffusion sur la sécurité. Même s'ils ne répondent pas, peut-être que quelqu'un d'autre silencieusement sur la liste vous répondra avec de l'aide.

Bonne chance !

1voto

Jablair Points 2495

Je ne l'ai pas essayé, mais Elcomsoft a publié un produit qui, selon eux, est capable de décrypter les sauvegardes, à des fins médico-légales. Ce n'est peut-être pas aussi cool que de développer une solution soi-même, mais ça pourrait être plus rapide.

http://www.elcomsoft.com/eppb.html

1 votes

Merci. Cela ne décrypte pas les sauvegardes en tant que telles : cela craque juste les clés. Je sais déjà comment faire ça... et c'est beaucoup plus simple que de décrypter la sauvegarde une fois que l'on a la clé.

0voto

Rohan Points 379

Je ne suis pas sûr, si c'est trop tard pour répondre, mais il semble qu'il y ait des outils disponibles qui peuvent le faire ! Je viens de tomber sur deux d'entre eux - Total Saver Pro y Extracteur de sauvegarde pour iPhone qui ont tous deux des versions gratuites et payantes. Il doit donc y avoir un moyen de le faire fonctionner.

-3voto

Nathan de Vries Points 10895

Vous devriez vous procurer une copie de l'utilitaire de ligne de commande mdhelper d'Erica Sadun ( Binaire OS X & source ). Il permet de répertorier et d'extraire le contenu des sauvegardes de l'iPhone/iPod Touch, y compris les bases de données du carnet d'adresses et des SMS, ainsi que d'autres métadonnées et réglages de l'application.

1 votes

C'est juste un lecteur de PList : Je peux déjà faire ce genre de choses en natif. Il ne supporte pas les sauvegardes cryptées, ce qui est ce que je recherche, et qui est au-delà de la portée de cet utilitaire.

0 votes

Avez-vous pris le temps d'essayer l'utilitaire ? Mes sauvegardes sont cryptées et il fait exactement ce que vous essayez de faire.

10 votes

Oui, et j'ai lu la source, aussi. Il ne gère pas les sauvegardes cryptées, et a été modifié pour la dernière fois avant la sortie de la prise en charge des sauvegardes cryptées par iTunes. Je suppose que vous voulez dire que vos sauvegardes sont cryptées ou que votre iPhone utilise un système de fichiers crypté, ce qui est une toute autre question. De même qu'il n'y a pas de support pour le cryptage dans le code, il n'y a pas non plus d'option pour passer un mot de passe dans les options de la ligne de commande. Et le code n'utilise aucun certificat ou trousseau de clés. J'aimerais bien qu'on me prouve que j'ai tort sur ce point, mais je ne pense vraiment pas que ce soit le cas ! J'apprécie la suggestion, cependant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X