Come decrittografare un backup crittografato di Apple iTunes iPhone?


84

Mi è stato chiesto da un certo numero di sfortunati utenti di iPhone di aiutarli a ripristinare i dati dai loro backup di iTunes. Questo è facile quando non sono crittografati, ma non quando sono crittografati, indipendentemente dal fatto che la password sia nota o meno.

In quanto tale, sto cercando di capire lo schema di crittografia utilizzato sui file mddata e mdinfo quando crittografati. Altrimenti non ho problemi a leggere questi file e ho creato alcune robuste librerie C # per farlo. (Se sei in grado di aiutare, non mi interessa quale lingua usi. È il principio che cerco qui!)

La "Guida alla distribuzione aziendale di iPhone OS" di Apple afferma che "i backup del dispositivo possono essere archiviati in formato crittografato selezionando l'opzione Crittografa backup iPhone nel pannello di riepilogo del dispositivo di iTunes. I file vengono crittografati utilizzando AES128 con una chiave a 256 bit. La chiave è archiviati in modo sicuro nel portachiavi dell'iPhone. "

Questo è un indizio abbastanza buono, e ci sono alcune buone informazioni qui su Stackoverflow sull'interoperabilità AES / Rijndael di iPhone che suggeriscono che è possibile utilizzare una dimensione della chiave di 128 e la modalità CBC.

A parte qualsiasi altro offuscamento, sono richiesti una chiave e un vettore di inizializzazione (IV) / sale.

Si potrebbe supporre che la chiave sia una manipolazione della "password di backup" che gli utenti sono invitati a inserire da iTunes e passata a " AppleMobileBackup.exe ", riempita in un modo dettato da CBC. Tuttavia, dato il riferimento al portachiavi dell'iPhone, mi chiedo se la "password di backup" non possa essere utilizzata come password su un certificato X509 o su una chiave privata simmetrica e che il certificato o la chiave privata stessa possa essere utilizzata come chiave. ( AES e il processo di crittografia / decrittografia di iTunes sono simmetrici.)

La flebo è un'altra questione e potrebbero essere alcune cose. Forse è una delle chiavi hard-coded in iTunes o nei dispositivi stessi .

Sebbene il commento di Apple sopra suggerisca che la chiave sia presente sul portachiavi del dispositivo, penso che non sia così importante. È possibile ripristinare un backup crittografato su un dispositivo diverso , il che suggerisce che tutte le informazioni rilevanti per la decrittografia sono presenti nel backup e nella configurazione di iTunes e che qualsiasi cosa esclusivamente sul dispositivo è irrilevante e sostituibile in questo contesto. Allora dove potrebbe essere la chiave?

Ho elencato i percorsi di seguito da una macchina Windows, ma è una gran quantità qualunque sia il sistema operativo che utilizziamo.

"\ Appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml" contiene un PList con una voce di dict "Portachiavi" al suo interno. "\ Programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist" contiene un PList con "DeviceCertificate", "HostCertificate" e "RootCertificate", che sembrano tutti certificati X509 validi. Lo stesso file sembra contenere anche chiavi asimmetriche "RootPrivateKey" e "HostPrivateKey" (la mia lettura suggerisce che potrebbero essere PKCS # 7). Inoltre, all'interno di ogni backup ci sono valori "AuthSignature" e "AuthData" nel file Manifest.plist, sebbene questi sembrino essere ruotati man mano che viene eseguito il backup incrementale di ogni file, suggeriscono che non siano così utili come chiave, a meno che qualcosa di veramente abbastanza coinvolto è stato fatto.

Ci sono molte cose fuorvianti là fuori che suggeriscono che ottenere dati da backup crittografati è facile. Non lo è e, per quanto ne so, non è stato fatto. Bypassare o disabilitare la crittografia del backup è un'altra questione e non è quello che sto cercando di fare.

Non si tratta di smantellare l'iPhone o qualcosa del genere. Tutto ciò che cerco qui è un mezzo per estrarre dati (foto, contatti, ecc.) Dai backup crittografati di iTunes come posso fare quelli non crittografati. Ho provato tutti i tipi di permutazioni con le informazioni che ho messo sopra ma non sono arrivato da nessuna parte. Apprezzerei qualsiasi pensiero o tecnica che potrei aver perso.


3
Aggiornamento da tre anni in poi: l'ho capito e l'ho trasformato in un prodotto che è disponibile gratuitamente. Ero sulla strada giusta sopra, ma è stata dura.
Aidan Fitzpatrick

hai un link per quel prodotto?
Thilo

1
Come hai chiesto, è l' iPhone Backup Extractor . Mentre vedrai che ci sono edizioni a pagamento del programma, la semplice vecchia edizione gratuita ti permetterà di ottenere file crittografati 4 alla volta.
Aidan Fitzpatrick

1
Vedo che sei riuscito a decrittografare il backup 10.2. Puoi condividere come l'hai ottenuto?
Niki

@Niki ho aggiornato la mia risposta di seguito per iOS 10
andrewdotn

Risposte:


107

I ricercatori di sicurezza Jean-Baptiste Bédrune e Jean Sigwald hanno presentato come farlo a Hack-in-the-box Amsterdam 2011 .

Da allora, Apple ha rilasciato un white paper sulla sicurezza iOS con maggiori dettagli su chiavi e algoritmi e Charlie Miller et al. hanno rilasciato il Manuale per hacker di iOS , che copre alcuni degli stessi motivi in ​​modo pratico. Quando iOS 10 è uscito per la prima volta, sono state apportate modifiche al formato di backup che Apple non ha inizialmente pubblicizzato, ma varie persone hanno decodificato le modifiche al formato .

I backup crittografati sono fantastici

La cosa grandiosa dei backup di iPhone crittografati è che contengono cose come le password WiFi che non sono presenti nei normali backup non crittografati. Come discusso nel white paper sulla sicurezza di iOS , i backup crittografati sono considerati più "sicuri", quindi Apple ritiene corretto includere informazioni più sensibili in essi.

Un avvertimento importante: ovviamente, decrittografare il backup del tuo dispositivo iOS rimuove la sua crittografia. Per proteggere la tua privacy e sicurezza, dovresti eseguire questi script solo su una macchina con crittografia dell'intero disco. Sebbene sia possibile per un esperto di sicurezza scrivere software che protegge le chiavi in ​​memoria, ad esempio utilizzando funzioni come VirtualLock()e SecureZeroMemory()tra molte altre cose, questi script Python memorizzeranno le chiavi di crittografia e le password in stringhe per essere raccolte da Python. Ciò significa che le tue chiavi e password segrete rimarranno nella RAM per un po ', da dove passeranno nel tuo file di scambio e sul tuo disco, dove un avversario può recuperarle. Questo vanifica completamente il punto di avere un backup crittografato.

Come decrittografare i backup: in teoria

Il white paper sulla sicurezza iOS spiega i concetti fondamentali di chiavi per file, classi di protezione, chiavi della classe di protezione e keybag meglio di quanto posso. Se non li conosci già, dedica qualche minuto alla lettura delle parti pertinenti.

Ora sai che ogni file in iOS è crittografato con la propria chiave di crittografia per file casuale, appartiene a una classe di protezione e le chiavi di crittografia per file sono archiviate nei metadati del file system, racchiuse nella chiave della classe di protezione.

Per decrittografare:

  1. Decodificare la keybag memorizzata nell'ingresso BackupKeyBagdi Manifest.plist. Una panoramica di alto livello di questa struttura è fornita nel white paper . L' iPhone Wiki descrive il formato binario: un campo di tipo stringa a 4 byte, un campo di lunghezza big-endian a 4 byte e quindi il valore stesso.

    I valori importanti sono le ITERazioni PBKDF2 e SALT, il doppio sale di protezione DPSLe il conteggio delle iterazioni DPIC, quindi per ciascuna protezione CLS, la WPKYchiave incartata.

  2. Utilizzando la password di backup derivare una chiave a 32 byte utilizzando il salt PBKDF2 corretto e il numero di iterazioni. Usa prima un round SHA256 con DPSLe DPIC, poi un round SHA1 con ITERe SALT.

    Unwrap ciascun tasto avvolto secondo RFC 3394 .

  3. Decrittografare il database manifest estraendo la classe di protezione a 4 byte e la chiave più lunga da ManifestKeyin Manifest.pliste scartandola. Ora hai un database SQLite con tutti i metadati dei file.

  4. Per ogni file di interesse, ottenere la chiave di crittografia per file crittografata per classe e il codice della classe di protezione cercando nella Files.filecolonna del database un plist binario contenente voci EncryptionKeye ProtectionClass. Rimuovere il tag della lunghezza di quattro byte iniziale EncryptionKeyprima dell'uso.

    Quindi, derivare la chiave di decrittografia finale scartandola con la chiave di classe che è stata scartata con la password di backup. Quindi decrittografare il file utilizzando AES in modalità CBC con IV zero.

Come decrittografare i backup: in pratica

Per prima cosa avrai bisogno di alcune dipendenze della libreria. Se sei su un Mac utilizzando un Python 2.7 o 3.7 installato in homebrew, puoi installare le dipendenze con:

CFLAGS="-I$(brew --prefix)/opt/openssl/include" \
LDFLAGS="-L$(brew --prefix)/opt/openssl/lib" \    
    pip install biplist fastpbkdf2 pycrypto

In formato codice sorgente eseguibile, ecco come decrittografare un singolo file delle preferenze da un backup di iPhone crittografato:

#!/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()

Che quindi stampa questo output:

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}

Credito extra

Il codice di protezione dati iphone pubblicato da Bédrune e Sigwald può decrittografare il portachiavi da un backup, comprese cose divertenti come il wifi salvato e le password del sito 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|
...

Quel codice non funziona più sui backup dai telefoni che utilizzano l'ultimo iOS, ma ci sono alcune porte Golang che sono state mantenute aggiornate consentendo l'accesso al portachiavi .


2
L'ho provato e ha funzionato dove ogni altro strumento ha fallito. Ho dovuto aggiungere anche un altro modulo python mancante: pip install --user pycrypto Grazie!
ALoopingIcon

2
Meraviglioso Utilizzando macports ho installato queste dipendenze: py27-m2crypto py27-cryptography
hyperspasm

2
Il link code.google.com era 404ing per me, ma ho trovato una versione aggiornata dello strumento (per OS X 10.10) su github.com/dinosec/iphone-dataprotection . Ha funzionato su OS X 10.11.5.
Aaron Brager

2
Se dovessi aggiornare il codice, saresti vicino a una divinità per me!
Jonas Zaugg

3
@JonasZaugg Ho aggiornato il codice di esempio per iOS 10. Spero che lo trovi utile.
andrewdotn

6

Spiacenti, ma potrebbe anche essere più complicato, coinvolgendo pbkdf2 o anche una sua variazione. Ascolta la sessione # 209 del WWDC 2010, che parla principalmente delle misure di sicurezza in iOS 4, ma menziona anche brevemente la crittografia separata dei backup e il modo in cui sono correlati.

Puoi essere abbastanza sicuro che senza conoscere la password, non c'è modo di decodificarla, anche con la forza bruta.

Supponiamo solo che tu voglia provare a consentire alle persone che CONOSCONO la password di accedere ai dati dei loro backup.

Temo che non ci sia modo di guardare il codice effettivo in iTunes per capire quali algoritmi sono utilizzati.

Ai tempi di Newton, dovevo decifrare i dati da un programma e potevo chiamare direttamente la sua funzione di decrittazione (conoscendo la password, ovviamente) senza la necessità di comprenderne nemmeno l'algoritmo. Non è più così facile, purtroppo.

Sono sicuro che ci sono persone esperte in giro che potrebbero decodificare il codice iTunes: devi solo farli interessare.

In teoria, gli algoritmi di Apple dovrebbero essere progettati in modo da rendere i dati ancora al sicuro (cioè praticamente indistruttibili con metodi di forza bruta) per qualsiasi aggressore che conosca l'esatto metodo di crittografia. E nella sessione 209 del WWDC sono andati abbastanza in profondità nei dettagli su ciò che fanno per ottenere questo risultato. Forse puoi effettivamente ottenere risposte direttamente dal team di sicurezza di Apple se dici loro le tue buone intenzioni. Dopotutto, anche loro dovrebbero sapere che la sicurezza mediante offuscamento non è realmente efficiente. Prova la loro mailing list sulla sicurezza. Anche se non rispondono, forse qualcun altro silenziosamente nell'elenco risponderà con un po 'di aiuto.

In bocca al lupo!


1

Non l'ho provato, ma Elcomsoft ha rilasciato un prodotto che sostengono sia in grado di decriptare i backup, per scopi forensi. Forse non è così bello come progettare una soluzione da soli, ma potrebbe essere più veloce.

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


1
Grazie. Questo non decrittografa i backup in quanto tali: semplicemente incrina le chiavi. So già come farlo ... ed è molto più semplice che decrittografare il backup una volta che hai la chiave.
Aidan Fitzpatrick

-3

Dovresti prendere una copia dell'utilità della riga di comando mdhelper di Erica Sadun (file binario e sorgente OS X ). Supporta l'elenco e l'estrazione dei contenuti dei backup di iPhone / iPod Touch, inclusi i database della rubrica e degli SMS e altri metadati e impostazioni dell'applicazione.


1
Questo è solo un lettore PList: posso già fare queste cose in modo nativo. Non supporta i backup crittografati che è ciò che cerco e che va oltre l'ambito di tale utilità.
Aidan Fitzpatrick

Ti sei preso il tempo per provare l'utilità? I miei backup sono crittografati e fa esattamente quello che stai cercando di fare.
Nathan de Vries

10
Sì, e ho letto anche la fonte. Non gestisce i backup crittografati ed è stato modificato l'ultima volta prima del rilascio del supporto di iTunes per i backup crittografati. Sospetto che intendi dire che i tuoi backup sono codificati o che il tuo iPhone utilizza un filesystem crittografato, che è tutta un'altra cosa. Oltre a non esserci supporto per la crittografia nel codice, ovviamente non c'è alcuna opzione per passare una password nelle opzioni della riga di comando. E il codice non utilizza certificati o portachiavi. Mi piacerebbe essere smentito su questo, ma davvero non credo di esserlo! Tuttavia apprezzo il suggerimento.
Aidan Fitzpatrick
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.