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

un certain nombre d'utilisateurs d'iPhone m'ont demandé de les aider à restaurer les données de leurs sauvegardes iTunes. C'est facile quand ils sont non cryptés, mais pas quand ils sont crypté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. Je n'ai aucun problème à lire ces fichiers sinon, et j'ai construit quelques bibliothèques C# robustes pour le faire. (Si vous êtes en mesure de vous aider, je n'est pas en charge la langue que vous utilisez. C'est le principe je suis après ici!)

the Apple "iPhone OS Enterprise Deployment Guide" déclare que "les sauvegardes de périphérique peuvent être stockées dans un format crypté en sélectionnant l'iPhone Crypt Option de sauvegarde dans le volet de résumé de périphérique d'iTunes. Les fichiers sont cryptés en utilisant AES128 avec une clé de 256 bits. La clé est stockée en toute sécurité dans le porte-clés de l'iPhone."

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

en dehors de toute autre confusion, une clé et un vecteur d'initialisation (IV)/sel sont nécessaires.

on peut supposer que la clé est une manipulation du" mot de passe de sauvegarde " que les utilisateurs sont invités à entrer par iTunes et passé à " AppleMobileBackup.exe ", rembourré d'une façon dictée par CBC. Cependant, compte tenu de la référence au porte-clés iPhone, je me demande si le "mot de passe de sauvegarde" ne pourrait pas être utilisé comme mot de passe sur un certificat X509 ou clé privée symétrique, et que le certificat ou la clé privée elle-même pourrait être utilisé comme 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 une des clés codée dans iTunes, ou dans le les appareils eux-mêmes .

bien que le commentaire D'Apple ci-dessus suggère que la clé est présente sur le porte-clés de l'appareil, je pense que ce n'est pas si important. On peut restaurer une sauvegarde cryptée à un périphérique différent , ce qui suggère que toutes les informations relatives au décryptage sont présentes dans la configuration de sauvegarde et d'iTunes, et que tout ce qui se trouve uniquement sur le périphérique n'est pas pertinent et peut être remplacé dans ce contexte. Alors où pourrait être la clé?

j'ai énuméré ci-dessous les chemins d'une machine Windows mais c'est beaucoup d'une muchness quel que soit L'OS que nous utilisons.

the " appdataRoamingApple ComputeriTunesitunesprefs.xml " contient un PList avec une entrée dict "Keychain". Le " programdataappleLockdown9037027da8f4bdefdea97d706703ca034c88bab.plist "contient un PList avec "DeviceCertificate", "HostCertificate", et "RootCertificate", tous qui semblent être valides x509 certs. Le même le fichier semble aussi contenir des clés asymétriques "RootPrivateKey" et "HostPrivateKey" (ma lecture suggère qu'elles pourraient être PKCS #7-enveloppées). De plus, à l'intérieur de chaque sauvegarde, il y a des valeurs "AuthSignature" et "AuthData" dans le Manifeste.plist file, bien que ceux-ci semblent être tournés comme chaque dossier obtient progressivement sauvegardé, a suggéré qu'ils ne sont pas si utiles comme une clé, à moins que quelque chose vraiment impliqué est fait.

il y a beaucoup de choses trompeuses là-bas suggérant obtenir des données à partir de sauvegardes cryptées est facile. Ce n'est pas, et à ma connaissance il n'a pas été fait. contourner ou désactiver le cryptage de sauvegarde est une autre affaire, et ce n'est pas ce que je cherche à faire.

il ne s'agit pas de hacker 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.) à partir des sauvegardes iTunes cryptées comme je peux les non cryptées. J'ai essayé toutes sortes de permutations avec l' les informations que j'ai mis plus haut, mais n'a mené nulle part. J'apprécierais toutes les idées ou techniques que j'aurais pu manquer.

76
demandé sur Community 2009-09-30 18:07:16

4 réponses

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

depuis, Apple a publié un iOS Security Whitepaper avec plus de détails sur les clés et les algorithmes, et Charlie Miller et al. avoir publié le iOS Hacker Manuel , qui couvre une partie de la même sol dans un mode. Quand iOS 10 est sorti pour la première fois, il y a eu des changements. au format de sauvegarde que Apple n'a pas fait connaître au début, mais divers les gens ingénierie inverse le changement de format .

les sauvegardes cryptées sont géniales

la grande chose au sujet des sauvegardes cryptées iPhone est qu'ils contiennent des choses comme les mots de passe WiFi qui ne sont pas dans les sauvegardes non cryptées régulières. Comme discuté dans le iOS Security Whitepaper , sauvegardes cryptées sont considérés comme plus "sûr", donc Apple considère qu'il est bon d'inclure plus des informations sensibles.

un avertissement important: évidemment, décrypter la sauvegarde de votre appareil iOS supprime son cryptage. Pour protéger votre vie privée et la sécurité, vous devriez n'exécutez ces scripts que sur une machine avec un cryptage complet. alors qu'il est possible pour un expert en sécurité d'écrire un logiciel qui protège les clés dans mémoire, p.ex. en utilisant des fonctions comme VirtualLock() et SecureZeroMemory() parmi beaucoup d'autres choses, ces Les scripts Python stockeront vos clés de cryptage et vos mots de passe dans les chaînes pour être récupérées par Python. Cela signifie Vos clés et mots de passe secrets vivra en RAM pendant un certain temps, d'où ils fuiront dans votre swap fichier sur votre disque, où l'adversaire peut les récupérer. Ce va à l'encontre de l'intérêt d'avoir une sauvegarde cryptée.

Comment décrypter les sauvegardes: en théorie

Le la Sécurité dans iOS livre Blanc explique les concepts fondamentaux des clés par fichier, des classes de protection, des clés de classe de protection et des porte-clés mieux que je peux. Si vous n'êtes pas déjà familier avec ceux-ci, prenez quelques-uns procès-verbal pour lire les parties pertinentes.

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

à décrypter:

  1. Décoder le keybag stockées dans le BackupKeyBag entrée de Manifest.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 4 octets champ de longueur big-endian, puis la valeur elle-même.

    les valeurs importantes sont les PBKDF2 ITER ations et SALT , le double sel de protection DPSL et compte d'itération DPIC , puis pour chaque protection CLS , la clé enveloppée WPKY .

  2. en utilisant le mot de passe de sauvegarde dérivez une clé de 32 octets en utilisant le PBKDF2 correct le sel et le nombre d'itérations. Première utilisation d'un SHA256 rond avec DPSL et DPIC , puis un sha1 round avec ITER et SALT .

    déballer chaque clé enveloppée conformément à RFC 3394 .

  3. déchiffrer la base de données du manifeste en tirant la classe de protection de 4 octets et la clé plus longue du ManifestKey dans Manifest.plist , et en la déballant. Vous avez maintenant une Base de données SQLite avec toutes les métadonnées des fichiers.

  4. pour chaque fichier d'intérêt, Obtenez le chiffrement par fichier chiffré par classe clé et Code de classe de protection en regardant dans la base de données Files.file colonne pour une liste binaire contenant EncryptionKey et ProtectionClass entrées. Rayer l'étiquette de longueur initiale de quatre octets de EncryptionKey avant utilisation.

    puis, dérivez la clé de déchiffrement finale en la déballant avec la classe clé déballée avec le mot de passe de sauvegarde. Puis décrypter le fichier utiliser AES en mode NFS avec zéro IV.

comment décrypter les sauvegardes: en pratique

sous forme de code source exécutable, voici comment déchiffrer la calculatrice fichier de préférences d'une sauvegarde iPhone cryptée:

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

import argparse
import base64
import getpass
import hashlib
import os.path
import pprint
import random
import shutil
import sqlite3
import stat
import string
import struct
import sys
import tempfile

import Crypto.Cipher.AES # https://www.dlitz.net/software/pycrypto/
import biplist
import fastpbkdf2

def main():
    ## Parse options
    parser = argparse.ArgumentParser()
    parser.add_argument('--backup-directory', dest='backup_directory',
                      default='data/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')
    parser.add_argument('--base64-passcode-key-pipe', dest='passcode_key_pipe',
                        help="""\
Provide a previously derived passcode key to save time doing PBDKF2 when
developing""")
    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)
    else:
        password = getpass.getpass('Backup password: ')

    if args.passcode_key_pipe:
        passcode_key = base64.decodestring(readpipe(args.passcode_key_pipe))
    else:
        passcode_key = None

    ## Unlock keybag with password
    if not keybag.unlockWithPasscode(password, passcode_key):
        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'), 'r') 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, 'w') as db_file:
            db_file.write(decrypted_data)
        conn = sqlite3.connect(db_filename)
        c = conn.cursor()
        c.execute("""
            SELECT fileID, domain, relativePath, file
            FROM Files
            WHERE relativePath LIKE '%/Preferences/com.apple.calculator.plist'
            ORDER BY 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 calculator preferences'
        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 = ["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, passcode_key=None):
        if passcode_key is None:
            passcode1 = fastpbkdf2.pbkdf2_hmac('sha256', passcode,
                                            self.attrs["DPSL"],
                                            self.attrs["DPIC"], 32)
            passcode_key = fastpbkdf2.pbkdf2_hmac('sha1', passcode1,
                                                self.attrs["SALT"],
                                                self.attrs["ITER"], 32)
        print '== Passcode key'
        print base64.encodestring(anonymize(passcode_key))
        for classkey in self.classKeys.values():
            if not classkey.has_key("WPKY"):
                continue
            k = classkey["WPKY"]
            if classkey["WRAP"] & WRAP_PASSCODE:
                k = AESUnwrap(passcode_key, 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 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

##
# 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):
    global anon_random, memo
    if ANONYMIZE_OUTPUT:
        if s in memo:
            return memo[s]
        possible_alphabets = [
            string.digits,
            string.digits + 'abcdef',
            string.letters,
            "".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([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 alors 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
VNfSPwXOK8mvKxTtmZ51JppAzrsG7gkWSiY8W7xnRX4=

== 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:
'bplist00\xd3\x01\x02\x03\x04\x05\x06\DisplayValue[MemoryValue_\x10\x14Trigono'
'metricModeKey_\x10%3.14159265358979323846264338327950288_\x10#2.71828182845904'
'5235360287471352662\x08\x08\x0f\x1c(?g\x8d\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\x00\x8e'

== pretty-printed calculator preferences
{'DisplayValue': '3.14159265358979323846264338327950288',
 'MemoryValue': '2.718281828459045235360287471352662',
 'TrigonometricModeKey': False}

crédit supplémentaire

le iphone-code de protection des données posté par Bédrune et Sigwald can décrypter le porte-clés à partir d'une sauvegarde, y compris des choses amusantes comme le wifi enregistré et les mots de passe de site 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 des téléphones en utilisant les dernières iOS, mais pas tous que beaucoup de choses ont changé ... laissez un commentaire si vous le souhaitez mettre à jour le code ci-dessus pour vider les mots de passe enregistrés ainsi ;p

84
répondu andrewdotn 2017-10-22 19:13:28

Désolé, mais il pourrait même être plus compliqué, impliquant pbkdf2, ou même une variante de celle-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 elles sont liées.

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

supposons que vous voulez essayer d'activer les personnes qui CONNAISSENT le mot de passe pour 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 comprendre quels algos sont employés.

à L'époque de Newton, j'ai dû déchiffrer les données d'un programme et j'ai pu appeler sa fonction de déchiffrement directement (en connaissant le mot de passe, bien sûr) sans même avoir besoin de sous-estimer son algorithme. Ce n'est plus si facile, malheureusement.

je suis sûr qu'il y a des gens qualifiés autour qui pourraient faire de l'ingénierie inverse que le code iTunes - vous avez juste à les intéresser.

en théorie, L'algos D'Apple devrait être conçu d'une manière qui rend les données encore sûres (c'est-à-dire pratiquement incassables par des méthodes de force brute) pour tout attaquant connaissant la méthode de cryptage exacte. Et dans la session 209 de la WWDC ils sont allés assez profondément dans les détails sur ce qu'ils font pour accomplir ceci. Peut-être que tu peux 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 devraient savoir que la sécurité par obscurcissement 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 silencieusement sur la liste répondra avec de l'aide.

bonne chance!

5
répondu Thomas Tempelmann 2010-09-26 18:09:42

N'ont pas essayé, mais Elcomsoft a publié un produit qu'ils prétendent être capable de déchiffrer des sauvegardes, pour les besoins de la criminalistique. Peut-être pas aussi cool que de concevoir une solution vous-même, mais ça pourrait être plus rapide.

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

1
répondu Jablair 2010-09-24 13:21:36

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

-3
répondu Nathan de Vries 2009-10-01 13:13:04