Як розшифрувати зашифровану резервну копію Apple iTunes iPhone?


84

Кілька нещасних користувачів iPhone мене попросили допомогти їм відновити дані зі своїх резервних копій iTunes. Це легко, коли вони зашифровані, але не коли вони зашифровані, незалежно від того, відомий пароль чи ні.

Як такий, я намагаюся з’ясувати схему шифрування, яка використовується у файлах mddata та mdinfo під час шифрування. У мене немає проблем з читанням цих файлів, і для цього я створив кілька надійних бібліотек C #. (Якщо ви можете допомогти, мені байдуже, якою мовою ви користуєтесь. Це принцип, за яким я тут!)

У «Посібнику з розгортання iPhone для підприємств iPhone» від Apple йдеться, що «Резервні копії пристроїв можна зберігати у зашифрованому форматі, вибравши опцію Шифрувати резервну копію iPhone на панелі підсумків пристрою iTunes. Файли шифруються за допомогою AES128 за допомогою 256-бітного ключа. надійно зберігаються у брелоку для iPhone. "

Це досить хороший підказка, і тут є деяка гарна інформація про Stackoverflow на сумісності iPhone AES / Rijndael, що пропонує розмір клавіш 128 і режим CBC.

Окрім будь-якої іншої затуманеності, потрібні ключ та вектор ініціалізації (IV) / сіль.

Можна припустити, що ключовим є маніпулювання "паролем резервної копії", який користувачі запрошують ввести через iTunes і передають до " AppleMobileBackup.exe ", доповнений у спосіб, продиктований CBC. Однак, беручи до уваги посилання на брелок для iPhone, мені цікаво, чи не може використовуватися "пароль резервної копії" як пароль для сертифіката X509 чи симетричного закритого ключа, і що сам сертифікат або закритий ключ може використовуватися як ключ. ( AES і процес шифрування / дешифрування iTunes симетричний.)

Інша справа - інша справа, і це може бути кілька речей. Можливо, це одна з клавіш, закодованих у iTunes, або в самих пристроях .

Незважаючи на те, що вищезазначений коментар Apple передбачає, що ключ присутній на брелоку пристрою, я думаю, це не так важливо. Можна відновити зашифровану резервну копію на інший пристрій, що передбачає, що вся інформація, що стосується дешифрування, присутня в резервній копії та конфігурації iTunes, і що будь-що виключно на пристрої є неактуальним та замінюваним у цьому контексті. То де може бути ключ?

Я перерахував шляхи нижче з машини Windows, але це багато в чому, яку б ОС ми не використовували.

"\ Appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml" містить ПЛІСТ із записом дикту "Брелок". "\ Programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist" містить список із "DeviceCertificate", "HostCertificate" та "RootCertificate", які, як видається, є дійсними сертифікатами X509. Цей самий файл також, схоже, містить асиметричні ключі "RootPrivateKey" та "HostPrivateKey" (моє читання припускає, що це може бути PKCS # 7). Крім того, у кожній резервній копії є значення "AuthSignature" та "AuthData" у файлі Manifest.plist, хоча вони, здається, обертаються в міру поступового резервного копіювання кожного файлу, припускаючи, що вони не такі корисні як ключ, якщо щось насправді робиться досить залучена.

Там є багато оманливих речей, які припускають, що отримання даних із зашифрованих резервних копій є простим. Це не так, і, наскільки мені відомо, цього не було зроблено. Обхід або вимкнення шифрування резервної копії - це зовсім інша справа, і це не те, що я хочу зробити.

Мова не йде про злом iPhone або щось подібне. Тут я лише шукаю засіб для вилучення даних (фотографій, контактів тощо) із зашифрованих резервних копій iTunes, оскільки я можу зашифрувати їх. Я пробував всілякі перестановки з інформацією, яку я виклав вище, але нікуди не дійшов. Буду вдячний за будь-які думки чи прийоми, які я міг би пропустити.


3
Оновлення починаючи з трьох років: Я зрозумів це і згорнув у продукт, який є у вільному доступі. Я був на правильному шляху вище, але це було важко.
Айдан Фіцпатрік,

у вас є посилання на цей товар?
Тіло

1
Як ви вже просили, це iPhone Backup Extractor . Хоча ви побачите, що існують платні версії програми, звичайне старе безкоштовне видання дозволить вам отримувати зашифровані файли по 4 за раз.
Aidan Fitzpatrick

1
Я бачу, що вам вдалося розшифрувати резервну копію 10.2. Чи можете ви поділитися, як ви цього досягли?
Нікі

@Niki Я оновив свою відповідь нижче для iOS 10
andrewdotn

Відповіді:


105

Дослідники з питань безпеки Жан-Батіст Бедруне та Жан Зігвальд представили, як це зробити, на Hack-in-the-box Amsterdam 2011 .

З тих пір Apple випустила довідковий документ про безпеку iOS із докладнішими відомостями про ключі та алгоритми, а також Чарлі Міллер та ін. випустили Довідник хакера iOS , який описує дещо з того самого, як це робити. Коли iOS 10 вперше вийшов, відбулися зміни у форматі резервної копії, які Apple спочатку не оприлюднювала, але різні люди змінили формат формату заново .

Зашифровані резервні копії чудові

Чудова річ у зашифрованих резервних копіях iPhone полягає в тому, що вони містять такі речі, як паролі WiFi, яких немає у звичайних незашифрованих резервних копіях. Як обговорювалося в Документі безпеки iOS , зашифровані резервні копії вважаються більш "безпечними", тому Apple вважає нормальним включати в них більш конфіденційну інформацію.

Важливе попередження: очевидно, дешифрування резервної копії пристрою iOS видаляє його шифрування. Для захисту вашої конфіденційності та безпеки слід запускати ці сценарії лише на машині з повнодисковим шифруванням. Хоча експерт із безпеки може писати програмне забезпечення, яке захищає ключі в пам'яті, наприклад, використовуючи такі функції, як VirtualLock()і SecureZeroMemory()серед іншого, ці скрипти Python зберігатимуть ваші ключі шифрування та паролі у рядках, які збиратиме сміття Python. Це означає, що ваші секретні ключі та паролі деякий час житимуть в оперативній пам'яті, звідки вони потраплять у ваш файл підкачки та на ваш диск, де супротивник може їх відновити. Це повністю перемагає сенс мати зашифровану резервну копію.

Як розшифрувати резервні копії: теоретично

IOS Security Whitepaper пояснює основні концепції кожного файлу ключів, класів захисту, ключі класу захисту, і keybags краще , ніж я можу. Якщо ви ще не знайомі з ними, знайдіть кілька хвилин, щоб прочитати відповідні частини.

Тепер ви знаєте, що кожен файл в iOS зашифрований власним випадковим ключем шифрування для кожного файлу, належить до класу захисту, а ключі шифрування для кожного файлу зберігаються в метаданих файлової системи, загорнуті в ключ класу захисту.

Щоб розшифрувати:

  1. Розшифруйте мішок ключів, що зберігається в BackupKeyBagзаписі Manifest.plist. Огляд цієї структури на високому рівні подано в технічному документі . IPhone вика описує бінарний формат: 4-байтовий типу рядка поле, тупоконечников поле довжини 4 байта, а потім саме значення.

    Важливими значеннями є дії PBKDF2 ITERі SALT, кількість подвійного захисту DPSLта кількість ітерацій DPIC, а потім для кожного захисту CLS- WPKYзагорнутий ключ.

  2. За допомогою пароля резервної копії виведіть 32-байтовий ключ, використовуючи правильну сіль PBKDF2 та кількість ітерацій. Спочатку використовуйте раунд SHA256 з DPSLі DPIC, потім раунд SHA1 з ITERі SALT.

    Розгорніть кожен загорнутий ключ відповідно до RFC 3394 .

  3. Розшифрувати маніфест бази даних, потягнувши клас захисту 4-байтовой і довший ключ від ManifestKeyдюйма Manifest.plist, і розгортає його. Тепер у вас є база даних SQLite з усіма метаданими файлів.

  4. Для кожного цікавого файлу отримайте зашифрований за класом ключ шифрування для кожного файлу та код класу захисту, шукаючи у Files.fileстовпці бази даних двійковий список, що містить EncryptionKeyта ProtectionClassзаписи. Зачистіть початковий чотирибайтовий тег довжини EncryptionKeyперед використанням.

    Потім виведіть остаточний ключ дешифрування, розгорнувши його за допомогою ключа класу, який було розгорнуто за допомогою пароля резервної копії. Потім розшифруйте файл за допомогою AES у режимі CBC з нульовим коефіцієнтом введення.

Як розшифрувати резервні копії: на практиці

Спочатку вам знадобляться деякі бібліотечні залежності. Якщо ви використовуєте mac, використовуючи Python 2.7 або 3.7, встановлений у саморобнику, ви можете встановити залежності за допомогою:

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

У запущеній формі вихідного коду ось як розшифрувати один файл налаштувань із зашифрованої резервної копії iPhone:

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

Що потім друкує цей результат:

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}

Додатковий кредит

Код захисту iphone-даних, розміщений Бедруном та Зігвальдом, може розшифрувати брелок із резервної копії, включаючи такі цікаві речі, як збережений wifi та паролі веб-сайтів:

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

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

Цей код більше не працює на резервних копіях з телефонів, що використовують останню версію iOS, але є деякі порти golang , які постійно оновлюються, дозволяючи отримати доступ до брелока .


2
Я спробував, і це спрацювало там, де не вдався кожен інший інструмент. Мені довелося додати ще один відсутній модуль python: pip install --user pycrypto Дякую!
ALoopingIcon

2
Чудово! Використання MacPorts Я встановив ці залежності: PY27-M2Crypto PY27-криптографія
hyperspasm

2
Посилання code.google.com для мене було 404, але я знайшов оновлену версію інструменту (для OS X 10.10) за адресою github.com/dinosec/iphone-dataprotection . Це працювало на OS X 10.11.5.
Аарон Брагер

2
Якби ти оновлював код, ти був би для мене близьким божеством!
Jonas Zaugg

3
@JonasZaugg Я оновив зразок коду для iOS 10. Сподіваюся, вам це буде корисно.
andrewdotn

6

Вибачте, але це може бути навіть складніше, включаючи pbkdf2 або навіть його варіацію. Послухайте сесію WWDC 2010 № 209, в якій в основному йдеться про заходи безпеки в iOS 4, але також коротко згадується про окреме шифрування резервних копій та їх взаємозв’язок.

Ви можете бути впевнені, що, не знаючи пароля, ви не зможете його розшифрувати, навіть грубою силою.

Давайте просто припустимо, що ви хочете спробувати дозволити людям, які ЗНАЮТЬ пароль, отримати доступ до даних своїх резервних копій.

Я боюся, що немає способу розглянути фактичний код в iTunes, щоб зрозуміти, які компанії використовуються.

Ще в дні Ньютона мені довелося розшифрувати дані з програми і мені вдалося викликати її функцію дешифрування безпосередньо (звичайно, знаючи пароль) без необхідності навіть недооцінювати її алгоритм. Це, на жаль, вже не так просто.

Я впевнений, що навколо є кваліфіковані люди, котрі можуть перепроектувати цей код iTunes - вам просто потрібно зацікавити їх.

Теоретично, алгоритми Apple повинні бути розроблені таким чином, щоб зробити дані все ще безпечними (тобто практично нерозривними методами грубої сили) для будь-якого зловмисника, який знає точний метод шифрування. І на сесії 209 WWDC вони заглибились у подробиці того, що вони роблять для цього. Можливо, ви дійсно можете отримати відповіді безпосередньо від команди безпеки Apple, якщо скажете їм про свої добрі наміри. Зрештою, навіть вони повинні знати, що безпека шляхом затуманення насправді не є ефективною. Спробуйте їх список розсилки безпеки. Навіть якщо вони не відповідають, можливо, хтось інший мовчки зі списку відповість за допомогою.

Удачі!


1

Ще не пробував, але Elcomsoft випустив продукт, який, на їх думку, здатний дешифрувати резервні копії для цілей криміналістики. Можливо, не настільки круто, як самостійно розробити рішення, але це може бути швидше.

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


1
Дякую. Це не розшифровує резервні копії як такі: вони просто зламають ключі. Я вже знаю, як це зробити ... і це набагато простіше, ніж розшифрувати резервну копію, коли у вас є ключ.
Aidan Fitzpatrick

-3

Вам слід взяти копію утиліти командного рядка mdhelper Еріки Садун ( двійковий файл і джерело OS X ). Він підтримує перелік та вилучення вмісту резервних копій iPhone / iPod Touch, включаючи бази даних адресної книги та SMS, а також інші метадані та налаштування програми.


1
Це просто зчитувач PList: я вже можу робити ці речі рідно. Він не підтримує зашифровані резервні копії, що я шукаю, і що виходить за рамки цієї утиліти.
Ейдан Фіцпатрік,

Ви знайшли час, щоб спробувати утиліту? Мої резервні копії зашифровані, і вони роблять саме те, що ви намагаєтесь зробити.
Натан де Фріз,

10
Так, і джерело я теж читав. Він не обробляє зашифровані резервні копії і востаннє був змінений до випуску підтримки iTunes для зашифрованих резервних копій. Я підозрюю, що ви маєте на увазі, що ваші резервні копії закодовані або що ваш iPhone використовує зашифровану файлову систему, що зовсім інша справа. Окрім того, що в коді немає підтримки шифрування, більш очевидно, що в параметрах командного рядка немає можливості передавати пароль. І в коді не використовуються сертифікати або брелки. Я хотів би, щоб довели, що я неправий у цьому, але я справді не думаю, що я! Однак я ціную пропозицію.
Ейдан Фіцпатрік,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.