84 votes

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

J'ai été demandé par un certain nombre de malheureux utilisateurs de l'iPhone pour les aider à restaurer les données à partir de leur iTunes sauvegardes. C'est facile quand ils ne sont pas cryptées, mais pas lorsqu'ils sont chiffrés, si oui ou non le mot de passe est connu.

En tant que tel, je suis à essayer de comprendre le système de cryptage utilisé sur mddata et mdinfo fichiers lorsqu'elles sont cryptées. Je n'ai pas de problèmes de lecture de ces fichiers, et ont construit robuste bibliothèques visual C# pour le faire. (Si vous êtes en mesure d'aider, je n'aime pas la langue que vous utilisez. C'est le principe je suis après ici!)

La Apple "iPhone OS Enterprise Guide de Déploiement", "Dispositif de sauvegardes peuvent être stockées dans un format crypté en sélectionnant le Chiffrer iPhone Option de sauvegarde de l'appareil volet résumé de iTunes. Les fichiers sont cryptés à l'aide de AES128 avec une clé de 256 bits. Les clés sont stockées en toute sécurité dans l'iPhone trousseau".

C'est une assez bonne idée, et il y a quelques bonnes infos ici sur Stackoverflow sur iPhone AES/Rijndael interopérabilité, ce qui suggère un keysize de 128 et le mode CBC peut être utilisé.

L'exclusion de toute autre dissimulation, l'un des principaux et vecteur d'initialisation (IV)/sel sont nécessaires.

On peut supposer que la clé est une manipulation de la "sauvegarde" mot de passe que les utilisateurs sont invités à entrer par iTunes et passés "AppleMobileBackup.exe"rembourrée, dans une mode dictée par la SRC. Toutefois, compte tenu de la référence à l'iPhone porte-clés, je me demande si le "mot de passe de sauvegarde" ne pourrait pas être utilisé comme un mot de passe sur un certificat X509 ou symétrique de la clé privée, et que le certificat ou la clé privée peut elle-même être utilisée en tant que clé. (AES et l'iTunes crypter/décrypter des processus est symétrique.)

Le IV est une autre affaire, et il pourrait être un certain nombre de choses. C'est peut-être l'une des clés codées en dur dans iTunes, ou dans les appareils eux-mêmes.

Même si Apple est le commentaire ci-dessus suggère que la clé est présente sur le trousseau, je pense que ce n'est pas si important que cela. On peut restaurer une sauvegarde cryptée à un différent de l'appareil, ce qui suggère que toutes les informations pertinentes pour le déchiffrement est présent dans la sauvegarde et la configuration de iTunes, et que quoi que ce soit uniquement sur l'appareil n'est pas pertinent et remplaçables dans ce contexte. Alors, où peut-être la clé?

J'ai chemins répertoriés ci-dessous à partir d'une machine Windows, mais c'est beaucoup de muchness quelque soit l'OS que nous utilisons.

Le "\appdata\Roaming\Apple Computer\iTunes\itunesprefs.xml" contient un fichier PList avec un "Trousseau" dict entrée. Le "\programdata\apple\Lockdown\09037027da8f4bdefdea97d706703ca034c88bab.plist" contient un fichier PList avec "DeviceCertificate", "HostCertificate", et "RootCertificate", qui semblent être valide certificats X509. Le même fichier semble également contenir des clés asymétriques "RootPrivateKey" et "HostPrivateKey" (ma lecture suggère que ce pourrait être PKCS #7-enveloppé). Aussi, au sein de chaque sauvegarde, il y a "AuthSignature" et "AuthData" valeurs " dans le Manifeste.fichier plist, bien que ceux-ci semblent être tourné que chaque fichier est progressivement sauvegardés, a suggéré qu'ils ne sont pas utiles, comme une clé, à moins que quelque chose de vraiment très impliqués, est en train d'être fait.

Il y a beaucoup d'induire en erreur les choses là-bas ce qui suggère l'obtention de données à partir des sauvegardes cryptées, c'est facile. Ce n'est pas, et à ma connaissance il n'a pas été fait. Le contournement ou la désactivation de la sauvegarde de chiffrement est une tout autre affaire, et n'est pas ce que je cherche à faire.

Ce n'est pas sur le piratage informatique en dehors de l'iPhone ou quelque chose comme ça. Tout ce que je suis après ici est un moyen pour extraire des données (photos, contacts, etc.) cryptée à partir de iTunes sauvegardes que je peux chiffré. J'ai essayé toutes sortes de permutations avec les informations que j'ai mis plus haut, mais n'a mené nulle part. J'apprécierais des idées ou des techniques que j'ai peut-être manqué.

106voto

andrewdotn Points 9183

Des chercheurs en sécurité Jean-Baptiste Bédrune et Jean Sigwald a présenté comment pour ce faire , au Hack-dans-la-boîte de Amsterdam, 2011.

Depuis, Apple a publié un livre Blanc de la Sécurité dans iOS avec plus de détails sur les touches et les algorithmes, et Charlie Miller et coll. ont publié le iOS Hacker Manuel, qui couvre une partie de la même sol dans un guide de la mode.

Heureusement, Bédrune et Sigwald ont open-source leur iphone-dataprotection code. Le décryptage de la sauvegarde est aussi simple que l'exécution de leur backup_tool script:

$ hg clone https://code.google.com/p/iphone-dataprotection/
$ python iphone-dataprotection/python_scripts/backup_tool.py \
    ~/Library/Application\ Support/MobileSync/Backup/long-hex-string \
    outdir
Device Name : My iPhone
Display Name : My iPhone
Last Backup Date : 2012-12-09 16:00:18
IMEI : 565988269232005
Serial Number : LN1G2AIND69G
Product Type : iPhone4,1
Product Version : 6.0.1
iTunes Version : 11.0
Extract backup to outdir ? (y/n)
y
Backup is encrypted
Enter backup password :
*******************
Writing Documents/products/97266p_bifold_3.jpg
...
...
...
Writing Media/DCIM/103APPLE/IMG_3874.JPG
You can decrypt the keychain using the following command :
python keychain_tool.py -d outdir/keychain-backup.plist outdir/Manifest.plist

La grande chose au sujet chiffré sauvegardes d'iPhone, c'est qu'ils contiennent des choses comme les mots de passe WiFi qui ne sont pas régulièrement non chiffrés sauvegardes. Comme discuté dans l' iOS livre Blanc de la Sécurité, des sauvegardes cryptées sont considérés comme plus "sécurisé", si Apple estime qu'il est ok pour inclure plus de des informations sensibles. Et, après l' backup_tool finitions, nous pouvons l'utilisation de déchiffrement pour obtenir les informations sensibles de retour en texte brut:

$ # You'll need to install the M2Crypto library before keychain_tool
$ # will work. These commands may be all you need:
$ brew install swig
...
$ pip install --user M2Crypto
...
$ echo | python iphone-dataprotection/python_scripts/keychain_tool.py \
    -d outdir/keychain-backup.plist outdir/Manifest.plist | less -S

If you have key835 for device 14b826ee48c5ea8b617f62fe12040c2d09af6b46 enter it (in hex)
--------------------------------------------------------------------------------------
|                              Passwords                                             |
-----------------------------------------------------------------------------------
|Service           |Account          |Data           |Access group  |Protection class|
--------------------------------------------------------------------------------------
|AirPort           |Ed's Coffee Shop |<3FrenchRoast  |apple         |AfterFirstUnlock|
...

Un avertissement important: de toute évidence, le décryptage de votre appareil iOS sauvegarde supprime son cryptage. Pour protéger votre confidentialité et votre sécurité, vous devez seulement exécuter ces scripts sur une machine de chiffrement intégral du disque. Alors qu'il est possible pour un expert en sécurité pour écrire un logiciel qui protège les clés dans de mémoire, par exemple en utilisant des fonctions comme VirtualLock()et SecureZeroMemory() parmi beaucoup d'autres choses, ces Les scripts Python va stocker vos clés de cryptage et les mots de passe dans les chaînes de être récupérées par Python. Cela signifie que votre secret clés et mots de passe vivra dans la mémoire RAM pour un certain temps, d'où ils auront une fuite dans votre swap fichier sur votre disque, où l'adversaire peut les récupérer. Cette va à l'encontre de l'intérêt d'avoir une sauvegarde cryptée.


Maintenant, vous savez de code open-source pour décrypter les sauvegardes, mais que faire si vous voulez savoir comment le code fonctionne, vous pouvez écrire votre propre?

L' iOS de Sécurité livre Blanc explique les concepts fondamentaux de par des touches de fichiers, classes de protection, classe de protection touches, et keybags mieux que je peux. Si vous n'êtes pas déjà familier avec ceux-ci, faire un peu de minutes pour lire les pages 6 à 12 maintenant.

Maintenant, vous savez que tous les fichiers iOS est chiffré avec sa propre aléatoire par clé de cryptage de fichier, appartient à une classe de protection, et le fichier par les clés de chiffrement sont stockés dans le système de fichiers de métadonnées, enveloppé dans l' classe de protection clé.

Dans des sauvegardes cryptées, seul le contenu du fichier est crypté. Le fichier les contenus sont stockés dans les mêmes haché noms de fichiers encryptés sauvegardes, les métadonnées ne sont pas chiffrées et dans le même format que discuté dans Comment analyser le Manifeste.mbdb fichier dans un iOS 4.0 Sauvegarde d'iTunes. La classe de protection sont les touches du mot de passe crypté dans la keybag à l'intérieur Metadata.plist, et la classe chiffré par fichier des clés de chiffrement stockées dans les métadonnées.

Déchiffrer:

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

    Les valeurs les plus importantes sont les PBKDF2 ITERations et SALT, puis pour chacun de protection de l' CLS, WPKY enveloppé clé.

  2. En utilisant le mot de passe de sauvegarde, qui est - "test" dans l'exemple ci-dessous, en déduire une de 32 octets de la clé à l'aide de la bonne PBKDF2 le sel et le nombre de itérations. Déballer chaque enveloppé clé selon RFC 3394.

  3. Pour chaque fichier de l'intérêt, demander à la classe chiffré par cryptage de fichier la clé et la classe de protection de code à partir des métadonnées dans l' .mbdble fichier. La clé de chiffrement commence quatre octets après la fin de la de hachage dans l' .mbdb le fichier, et la classe de protection est le nombre d'octets après la fin de la longueur du fichier.

    Ensuite, en tirer le final de la clé de déchiffrement défaire avec la clé de classe qui a été déballé avec le mot de passe de sauvegarde. Le déchiffrer le fichier à l'aide de l'algorithme AES en mode CBC avec un zéro IV.

Dans praticable forme de code source, voici comment décrypter la calculatrice fichier de préférences à partir d'un chiffré de l'iPhone de sauvegarde en data/encryptedavec mot de passe test:

#!/usr/bin/env python2.7
# coding: UTF-8

# default to True to avoid leaking secrets
ANONYMIZE_OUTPUT = True

import PBKDF2 # http://iphone-dataprotection.googlecode.com/hg-history/tip/python_scripts/crypto/PBKDF2.py
import bplist # https://github.com/farcaller/bplist-python/raw/master/bplist.py
import Crypto.Cipher.AES # https://www.dlitz.net/software/pycrypto/

import hashlib
import os.path
import pprint
import sys

BACKUP_DIR = "data/encrypted"

def main():
    with open(os.path.join(BACKUP_DIR, 'Manifest.plist'), 'rb') as infile:
        manifest_plist = bplist.BPlistReader.plistWithString(infile.read())
    keybag = Keybag(manifest_plist['BackupKeyBag'])
    # the actual keys are unknown, but the wrapped keys are known
    keybag.printClassKeys()
    if not keybag.unlockWithPasscode('test'):
        raise Exception('Could not unlock keybag; bad password?')
    # now the keys are known too
    keybag.printClassKeys()

    for item in process_mbdb_file(
            os.path.join(BACKUP_DIR, 'Manifest.mbdb')).values():
        filename = item['filename']
        if not filename.endswith('calculator.plist'):
            continue
        encryption_key = item['unknown1'][4:]
        protection_class = item['flag']
        backup_filename = os.path.join(
            BACKUP_DIR,
            hashlib.sha1(item['domain'] + '-' + item['filename']).hexdigest())
        with open(backup_filename, 'rb') as infile:
            data = infile.read()
        print '== encrypted data:'
        print wrap(data)
        print

        key = keybag.unwrapKeyForClass(protection_class, encryption_key)
        # truncate to actual length, because encryption may introduce padding
        decrypted_data = AESdecryptCBC(data, key)[:item['filelen']]
        print '== decrypted data:'
        print wrap(decrypted_data)
        print

        print '== pretty-printed calculator preferences'
        pprint.pprint(bplist.BPlistReader.plistWithString(decrypted_data))

##
# this section is mostly copied from parts of iphone-dataprotection
# http://code.google.com/p/iphone-dataprotection/

import struct

CLASSKEY_TAGS = ["CLAS","WRAP","WPKY", "KTYP", "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 == "TYPE":
                self.type = data
                if self.type > 3:
                    print "FAIL: keybag type > 3 : %d" % self.type
            elif tag == "UUID" and self.uuid is None:
                self.uuid = data
            elif tag == "WRAP" and self.wrap is None:
                self.wrap = data
            elif tag == "UUID":
                if currentClassKey:
                    self.classKeys[currentClassKey["CLAS"]] = currentClassKey
                currentClassKey = {"UUID": data}
            elif tag in CLASSKEY_TAGS:
                currentClassKey[tag] = data
            else:
                self.attrs[tag] = data
        if currentClassKey:
            self.classKeys[currentClassKey["CLAS"]] = currentClassKey

    def unlockWithPasscode(self, passcode):
        passcodekey = PBKDF2.PBKDF2(passcode, self.attrs["SALT"],
                                    iterations=self.attrs["ITER"]).read(32)
        for classkey in self.classKeys.values():
            if not classkey.has_key("WPKY"):
                continue
            k = classkey["WPKY"]
            if classkey["WRAP"] & WRAP_PASSCODE:
                k = AESUnwrap(passcodekey, classkey["WPKY"])
                if not k:
                    return False
                classkey["KEY"] = k
        return True

    def unwrapKeyForClass(self, protection_class, persistent_key):
        ck = self.classKeys[protection_class]["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["VERS"]
        print "Keybag iterations: %d, iv=%s" % (
            self.attrs["ITER"], anonymize(self.attrs["SALT"].encode('hex')))
        print "Keybag UUID: %s" % anonymize(self.uuid.encode("hex"))
        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("WRAP","")).ljust(5),
                 KEY_TYPES[ck.get("KTYP",0)].ljust(11),
                 anonymize(ck.get("KEY", "").encode("hex")).ljust(65),
                 anonymize(ck.get("WPKY", "").encode("hex")).ljust(65),
                 ck.get("PBKY", "").encode("hex")])
        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 xrange(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 xrange(1,n+1):
        R[i] = C[i]

    for j in reversed(xrange(0,6)):
        for i in reversed(xrange(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 = "".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

##
# this .mbdb-parsing code is from http://stackoverflow.com/q/3085153/14558:

def getint(data, offset, intsize):
    """Retrieve an integer (big-endian) and new offset from the current offset"""
    value = 0
    while intsize > 0:
        value = (value<<8) + ord(data[offset])
        offset = offset + 1
        intsize = intsize - 1
    return value, offset

def getstring(data, offset):
    """Retrieve a string and new offset from the current offset into the data"""
    if data[offset] == chr(0xFF) and data[offset+1] == chr(0xFF):
        return '', offset+2 # Blank string
    length, offset = getint(data, offset, 2) # 2-byte length
    value = data[offset:offset+length]
    return value, (offset + length)

def process_mbdb_file(filename):
    mbdb = {} # Map offset of info in this file => file info
    data = open(filename).read()
    if data[0:4] != "mbdb": raise Exception("This does not look like an MBDB file")
    offset = 4
    offset = offset + 2 # value x05 x00, not sure what this is
    while offset < len(data):
        fileinfo = {}
        fileinfo['start_offset'] = offset
        fileinfo['domain'], offset = getstring(data, offset)
        fileinfo['filename'], offset = getstring(data, offset)
        fileinfo['linktarget'], offset = getstring(data, offset)
        fileinfo['datahash'], offset = getstring(data, offset)
        fileinfo['unknown1'], offset = getstring(data, offset)
        fileinfo['mode'], offset = getint(data, offset, 2)
        fileinfo['unknown2'], offset = getint(data, offset, 4)
        fileinfo['unknown3'], offset = getint(data, offset, 4)
        fileinfo['userid'], offset = getint(data, offset, 4)
        fileinfo['groupid'], offset = getint(data, offset, 4)
        fileinfo['mtime'], offset = getint(data, offset, 4)
        fileinfo['atime'], offset = getint(data, offset, 4)
        fileinfo['ctime'], offset = getint(data, offset, 4)
        fileinfo['filelen'], offset = getint(data, offset, 8)
        fileinfo['flag'], offset = getint(data, offset, 1)
        fileinfo['numprops'], offset = getint(data, offset, 1)
        fileinfo['properties'] = {}
        for ii in range(fileinfo['numprops']):
            propname, offset = getstring(data, offset)
            propval, offset = getstring(data, offset)
            fileinfo['properties'][propname] = propval
        mbdb[fileinfo['start_offset']] = fileinfo
    return mbdb

##
# and here are some utility functions, one making sure I don't leak my
# secret keys when posting the output on Stack Exchange

if ANONYMIZE_OUTPUT:
    memo = {}
    def anonymize(s):
        global memo
        if s in memo:
            return memo[s]
        import random
        import string
        r = random.Random(0)
        possible_alphabets = [
            string.digits,
            string.digits + 'abcdef',
            "".join(chr(x) for x in range(0, 256)),
        ]
        for a in possible_alphabets:
            if all(c in a for c in s):
                alphabet = a
                break
        ret = "".join([r.choice(alphabet) for i in range(len(s))])
        memo[s] = ret
        return ret
else:
    def anonymize(s): 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)

if __name__ == '__main__':
    main()

Qui imprime ensuite cette sortie:

== Keybag
Keybag type: Backup keybag (1)
Keybag version: 3
Keybag iterations: 10000, iv=dc6486c479e84c94efce4bea7169ef7d4c80b6da
Keybag UUID: dc6486c479e84c94efce4bea7169ef7d
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Class                                                WRAP Type       Key                                                              WPKY                                                             Public key
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NSFileProtectionComplete                             2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionCompleteUnlessOpen                   2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionCompleteUntilFirstUserAuthentication 2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionNone                                 2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionRecovery?                            3    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed

kSecAttrAccessibleWhenUnlocked                       2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAfterFirstUnlock                   2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAlways                             2    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleWhenUnlockedThisDeviceOnly         3    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly     3    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAlwaysThisDeviceOnly               3    AES                                                                         dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed

== Keybag
Keybag type: Backup keybag (1)
Keybag version: 3
Keybag iterations: 10000, iv=dc6486c479e84c94efce4bea7169ef7d4c80b6da
Keybag UUID: dc6486c479e84c94efce4bea7169ef7d
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Class                                                WRAP Type       Key                                                              WPKY                                                             Public key
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NSFileProtectionComplete                             2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionCompleteUnlessOpen                   2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionCompleteUntilFirstUserAuthentication 2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionNone                                 2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
NSFileProtectionRecovery?                            3    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed

kSecAttrAccessibleWhenUnlocked                       2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAfterFirstUnlock                   2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAlways                             2    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleWhenUnlockedThisDeviceOnly         3    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly     3    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed
kSecAttrAccessibleAlwaysThisDeviceOnly               3    AES        dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9 dc6486c479e84c94efce4bea7169ef7d4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceed

== encrypted data:
"\xcc\x95U\xbf\xbc\x03%\xff\xe3m\x9f\xdb=~}\xbb\xa1\x8cp\xf4\xe2\xa2\x81G8\xf7"
"\x8f\xc4\x8aI\xf4]\x0e\xca\xd4\xb8\xb6\xfb'\x07\x9e\xdc,\xfe\xf5\xd7a\ry\xd8B"
"\xe4(\xbb56\xbd\x82/1\x86\xaf\xe2\xeac\xccu\xc0\xa6\xac5\xfa\x1d\xf7\xbf#HVXq"
"\xe3\x99`nW\xbb+\xc9\x9e\xf2\x1d\xbf\x87\x95\\\xfd\x1f oW\xcb\x0bE\x98\x02\x86"
"\x03\xfe\x90aL\xad(\xd0\x01D\xb5;\x86\x98\xcc\xf9\x0b\x9cLQ8\xaf\xac\xae\x04"
"\x1cSpF\x00'R\\\xd7\xcb\xefx\xa4`\xcc\xb6\xc7\x94\x98\x91\x11Z\xb1_\xda\xa1"
"\x8a\xce\xd1"

== decrypted data:
'bplist00\xd3\x01\x02\x03\x04\x05\x06_\x10\x14TrigonometricModeKey[MemoryValue'
'\\DisplayValue\x08_\x10(0.41666666666666666666666666666666666666U57.84\x08\x0f'
'&2?@k\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00'
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00q'

== pretty-printed calculator preferences
{'DisplayValue': '57.84',
 'MemoryValue': '0.41666666666666666666666666666666666666',
 'TrigonometricModeKey': False}

Voir l' iphone-dataprotection code source pour les cas ce n'est pas la poignée, comme la courbe elliptique clés. Notez que iphone-dataprotection gère beaucoup plus que juste des sauvegardes, comme la fissuration de la protection des données sur le périphérique, et en utilisant des disques virtuels.

6voto

Thomas Tempelmann Points 2849

Désolé, mais il pourrait même être plus compliqué, impliquant pbkdf2, ou même une variante de celle-ci. Écouter de la WWDC 2010 session #209, principalement des discussions sur les mesures de sécurité dans iOS 4, mais aussi mentionne brièvement le séparer de cryptage des sauvegardes et de la façon dont ils sont liés.

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

Disons simplement supposer que vous voulez essayer de permettre aux personnes qui CONNAISSENT le mot de passe pour accéder aux données de leurs sauvegardes.

J'ai peur, il n'y a pas moyen de contourner en regardant le code dans iTunes afin de comprendre ce qui algos sont employées.

De retour dans le Newton jours, j'ai eu à déchiffrer les données à partir d'un programme et a été en mesure d'appeler son décryptage de la fonction directement (à savoir le mot de passe, bien sûr), sans la nécessité même de comprendre son algorithme. Il n'est pas facile plus, malheureusement.

Je suis sûr qu'il ya des gens habiles qui pourrait inverser l'ingénierie que de code iTunes - vous avez juste à les intéresser.

En théorie, Apple algos devraient être conçus de manière à ce que les données restent en sécurité (c'est à dire pratiquement incassable par la force brute méthodes) à un attaquant de savoir exactement à la méthode de chiffrement. Et dans la WWDC session 209, ils sont allés assez profondément dans les détails à propos de ce qu'ils font pour accomplir cette tâche. Peut-être que vous pouvez réellement obtenir des réponses directement auprès d'Apple de l'équipe de sécurité, si vous leur dites de vos bonnes intentions. Après tout, même qu'ils devraient savoir que la sécurité par l'obfuscation est pas vraiment efficace. Essayez la sécurité de leur liste de diffusion. Même si elles ne repond pas, peut-être quelqu'un d'autre en silence sur la liste de répondre avec un peu d'aide.

Bonne chance!

1voto

Jablair Points 2495

Je ne l'ai pas essayé, mais Elcomsoft a publié un produit qui, à son avis, est capable de décrypter les sauvegardes, à des fins d'investigation. Peut-être pas aussi cool que de concevoir vous-même une solution, mais cela pourrait être plus rapide.

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

0voto

Rohan Points 379

Pas sûr, s'il est trop tard pour répondre, mais il semble qu'il existe des outils pour le faire! Je viens d'en découvrir 2: Total Saver Pro et iPhone Backup Extractor , tous deux disponibles en version gratuite et payante. Donc, il doit y avoir un moyen de le faire fonctionner.

-3voto

Nathan de Vries Points 10895

Vous devez vous procurer une copie de l'utilitaire de ligne de commande mdhelper d'Erica Sadun ( source et binaire OS X ). Il prend en charge la liste et l'extraction du contenu des sauvegardes sur iPhone / iPod Touch, y compris les bases de données de carnet d'adresses et de SMS, ainsi que d'autres métadonnées et paramètres d'application.

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