Làm thế nào để giải mã một bản sao lưu Apple iTunes iPhone đã được mã hóa?


84

Tôi đã được một số người dùng iPhone không may yêu cầu giúp họ khôi phục dữ liệu từ bản sao lưu iTunes của họ. Điều này rất dễ dàng khi chúng không được mã hóa, nhưng không phải khi chúng được mã hóa, cho dù mật khẩu có được biết hay không.

Do đó, tôi đang cố gắng tìm ra sơ đồ mã hóa được sử dụng trên các tệp mddata và mdinfo khi được mã hóa. Tôi không gặp vấn đề gì khi đọc các tệp này và đã xây dựng một số thư viện C # mạnh mẽ để làm như vậy. (Nếu bạn có thể giúp, tôi không quan tâm bạn sử dụng ngôn ngữ nào. Đó là nguyên tắc tôi theo đuổi ở đây!)

"Hướng dẫn triển khai iPhone OS Enterprise" của Apple nêu rõ rằng "Các bản sao lưu thiết bị có thể được lưu trữ ở định dạng mã hóa bằng cách chọn tùy chọn Encrypt iPhone Backup trong ngăn tóm tắt thiết bị của iTunes. Các tệp được mã hóa bằng AES128 với khóa 256 bit. Chìa khóa là được lưu trữ an toàn trong chuỗi khóa iPhone. "

Đó là một manh mối khá tốt và có một số thông tin tốt ở đây về khả năng tương tác của Stackoverflow trên iPhone AES / Rijndael đề xuất kích thước phím là 128 và chế độ CBC có thể được sử dụng.

Ngoài bất kỳ sự xáo trộn nào khác, cần có khóa và vectơ khởi tạo (IV) / muối.

Người ta có thể cho rằng khóa là một thao tác của "mật khẩu dự phòng" mà người dùng được iTunes nhắc nhập và chuyển tới " AppleMobileBackup.exe ", được chèn theo kiểu do CBC ra lệnh. Tuy nhiên, do tham chiếu đến chuỗi khóa iPhone, tôi tự hỏi liệu "mật khẩu dự phòng" có thể không được sử dụng làm mật khẩu trên chứng chỉ X509 hoặc khóa cá nhân đối xứng hay không và bản thân chứng chỉ hoặc khóa cá nhân có thể được sử dụng làm khóa. ( AES và quá trình mã hóa / giải mã iTunes là đối xứng.)

IV là một vấn đề khác, và nó có thể là một vài thứ. Có lẽ đó là một trong những chìa khóa được mã hóa cứng vào iTunes hoặc vào chính các thiết bị .

Mặc dù bình luận của Apple ở trên cho thấy chìa khóa hiện diện trên chuỗi khóa của thiết bị, nhưng tôi nghĩ điều này không quan trọng lắm. Người ta có thể khôi phục một bản sao lưu được mã hóa vào một thiết bị khác , điều này cho thấy tất cả thông tin liên quan đến việc giải mã đều có trong bản sao lưu và cấu hình iTunes, và bất kỳ thứ gì chỉ có trên thiết bị đều không liên quan và có thể thay thế được trong bối cảnh này. Vì vậy, đâu có thể là chìa khóa?

Tôi đã liệt kê các đường dẫn bên dưới từ máy Windows nhưng nó quá nhiều bất kỳ hệ điều hành nào chúng tôi sử dụng.

"\ Appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml" chứa một PList với mục nhập dict "Keychain" trong đó. "\ Programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist" chứa một PList với "DeviceCertificate", "HostCertificate" và "RootCertificate", tất cả đều có vẻ là chứng chỉ X509 hợp lệ. Tệp tương tự dường như cũng chứa các khóa không đối xứng "RootPrivateKey" và "HostPrivateKey" (bài đọc của tôi cho thấy chúng có thể là PKCS # 7 được bao bọc). Ngoài ra, bên trong mỗi bản sao lưu có các giá trị "AuthSignature" và "AuthData" trong tệp Manifest.plist, mặc dù các giá trị này dường như được xoay khi mỗi tệp được sao lưu dần dần, chúng được đề xuất rằng chúng không hữu ích như một khóa, trừ khi có điều gì đó thực sự khá liên quan đang được thực hiện.

Có rất nhiều thứ gây hiểu lầm cho thấy việc lấy dữ liệu từ các bản sao lưu được mã hóa thật dễ dàng. Nó không phải, và theo hiểu biết của tôi, nó đã không được thực hiện. Bỏ qua hoặc vô hiệu hóa mã hóa sao lưu hoàn toàn là một vấn đề khác và không phải là điều tôi muốn làm.

Đây không phải là việc hack iPhone hay bất cứ thứ gì tương tự. Tất cả những gì tôi muốn ở đây là một phương tiện để trích xuất dữ liệu (ảnh, danh bạ, v.v.) từ các bản sao lưu iTunes được mã hóa vì tôi có thể những bản sao lưu không được mã hóa. Tôi đã thử tất cả các loại hoán vị với thông tin tôi đã đưa ở trên nhưng chẳng có kết quả gì. Tôi đánh giá cao bất kỳ suy nghĩ hoặc kỹ thuật nào mà tôi có thể đã bỏ qua.


3
Cập nhật từ ba năm trở đi: Tôi đã tìm ra nó và biến nó thành một sản phẩm có sẵn miễn phí. Tôi đã đi đúng hướng ở trên, nhưng thật khó.
Aidan Fitzpatrick

bạn có một liên kết cho sản phẩm đó?
Thilo

1
Như bạn đã hỏi, đó là iPhone Backup Extractor . Trong khi bạn sẽ thấy có các phiên bản trả phí của chương trình, phiên bản miễn phí đơn giản cũ sẽ cho phép bạn tải ra 4 tệp được mã hóa cùng một lúc.
Aidan Fitzpatrick

1
Tôi thấy rằng bạn đã giải mã được bản sao lưu 10.2. Bạn có thể vui lòng chia sẻ cách bạn đạt được điều đó không?
Niki,

@Niki Tôi đã cập nhật câu trả lời của mình bên dưới cho iOS 10
andrewdotn

Câu trả lời:


105

Các nhà nghiên cứu bảo mật Jean-Baptiste Bédrune và Jean Sigwald đã trình bày cách thực hiện điều này tại Hack-in-the-box Amsterdam 2011 .

Kể từ đó, Apple đã phát hành Báo cáo chính thức về bảo mật iOS với nhiều thông tin chi tiết hơn về các khóa và thuật toán, và Charlie Miller et al. đã phát hành Sổ tay tin tặc iOS, cuốn sách này bao gồm một số điều tương tự về cách làm. Khi iOS 10 lần đầu tiên ra mắt, có những thay đổi đối với định dạng sao lưu mà Apple không công bố lúc đầu, nhưng nhiều người đã thiết kế ngược lại các thay đổi định dạng .

Các bản sao lưu được mã hóa rất tuyệt vời

Điều tuyệt vời về các bản sao lưu iPhone được mã hóa là chúng chứa những thứ như mật khẩu WiFi không có trong các bản sao lưu không được mã hóa thông thường. Như đã thảo luận trong Báo cáo chính thức về bảo mật iOS , các bản sao lưu được mã hóa được coi là “an toàn” hơn, vì vậy Apple cho rằng việc đưa thêm thông tin nhạy cảm vào đó là điều có thể chấp nhận được.

Một cảnh báo quan trọng: rõ ràng, việc giải mã bản sao lưu thiết bị iOS của bạn sẽ xóa mã hóa của nó. Để bảo vệ quyền riêng tư và bảo mật của mình, bạn chỉ nên chạy các tập lệnh này trên máy có mã hóa toàn đĩa. Mặc dù chuyên gia bảo mật có thể viết phần mềm bảo vệ các khóa trong bộ nhớ, chẳng hạn bằng cách sử dụng các chức năng như VirtualLock()SecureZeroMemory()trong số nhiều thứ khác, các tập lệnh Python này sẽ lưu trữ các khóa mã hóa và mật khẩu của bạn trong chuỗi để Python thu thập rác. Điều này có nghĩa là khóa bí mật và mật khẩu của bạn sẽ tồn tại trong RAM một thời gian, từ đó chúng sẽ bị rò rỉ vào tệp hoán đổi và vào đĩa của bạn, nơi kẻ thù có thể khôi phục chúng. Điều này hoàn toàn đánh bại quan điểm có một bản sao lưu được mã hóa.

Cách giải mã các bản sao lưu: về lý thuyết

Các iOS bạch về bảo mật giải thích các khái niệm cơ bản của các phím cho mỗi tập tin, các lớp bảo vệ, khóa lớp bảo vệ, và keybags tốt hơn tôi có thể. Nếu bạn chưa quen với những điều này, hãy dành vài phút để đọc các phần liên quan.

Bây giờ bạn biết rằng mọi tệp trong iOS đều được mã hóa bằng khóa mã hóa ngẫu nhiên cho mỗi tệp riêng của nó, thuộc một lớp bảo vệ và các khóa mã hóa cho mỗi tệp được lưu trữ trong siêu dữ liệu hệ thống tệp, được bao bọc trong khóa lớp bảo vệ.

Để giải mã:

  1. Giải mã túi chìa khóa được lưu trữ trong BackupKeyBagmục nhập của Manifest.plist. Tổng quan cấp cao về cấu trúc này được đưa ra trong sách trắng . Các iPhone Wiki mô tả định dạng nhị phân: a 4-byte kiểu chuỗi lĩnh vực, một 4-byte lĩnh vực chiều dài lớn về cuối nhỏ, và sau đó là giá trị riêng của mình.

    Các giá trị quan trọng là các ITERations PBKDF2 SALT, muối bảo vệ kép DPSLvà số lần lặp DPIC, sau đó đối với mỗi bảo vệ CLSWPKYkhóa được bọc.

  2. Sử dụng mật khẩu dự phòng sẽ lấy ra khóa 32 byte sử dụng muối PBKDF2 chính xác và số lần lặp. Đầu tiên sử dụng vòng SHA256 với DPSLDPIC, sau đó sử dụng vòng SHA1 với ITERSALT.

    Mở từng khóa được bọc theo RFC 3394 .

  3. Giải mã cơ sở dữ liệu tệp kê khai bằng cách kéo lớp bảo vệ 4 byte và khóa dài hơn từ bên ManifestKeytrong Manifest.plistvà mở gói. Bây giờ bạn có cơ sở dữ liệu SQLite với tất cả siêu dữ liệu tệp.

  4. Đối với mỗi tệp quan tâm, hãy lấy khóa mã hóa từng tệp được mã hóa theo lớp và mã lớp bảo vệ bằng cách tìm trong Files.filecột cơ sở dữ liệu để tìm một plist nhị phân chứa EncryptionKeyProtectionClasscác mục nhập. Bỏ thẻ có độ dài bốn byte ban đầu EncryptionKeytrước khi sử dụng.

    Sau đó, lấy khóa giải mã cuối cùng bằng cách mở nó bằng khóa lớp đã được mở bằng mật khẩu dự phòng. Sau đó giải mã tệp bằng AES ở chế độ CBC với số không IV.

Cách giải mã các bản sao lưu: trong thực tế

Trước tiên, bạn sẽ cần một số phụ thuộc thư viện. Nếu bạn đang sử dụng máy Mac sử dụng Python 2.7 hoặc 3.7 được cài đặt sẵn homebrew, bạn có thể cài đặt các phụ thuộc với:

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

Ở dạng mã nguồn chạy được, đây là cách giải mã một tệp tùy chọn duy nhất từ ​​bản sao lưu iPhone được mã hóa:

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

Sau đó sẽ in đầu ra này:

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}

Tín dụng thêm

Các đang iphone-dataprotection đăng bởi Bédrune và Sigwald thể giải mã keychain từ một bản sao lưu, trong đó có những điều thú vị như mật khẩu wifi và trang web đã lưu:

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

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

Mã đó không còn hoạt động trên các bản sao lưu từ điện thoại sử dụng iOS mới nhất, nhưng có một số cổng golang đã được cập nhật cho phép truy cập vào chuỗi khóa .


2
Tôi đã thử nó và nó hoạt động khi mọi công cụ khác không thành công. Tôi đã phải thêm một mô-đun python bị thiếu khác: pip install --user pycrypto Cảm ơn!
ALoopingIcon 29/12/12

2
Tuyệt vời! Sử dụng macports, tôi đã cài đặt các phụ thuộc này: py27-m2crypto py27-cryptography
hyperspasm,

2
Liên kết code.google.com đối với tôi là 404, nhưng tôi đã tìm thấy phiên bản cập nhật của công cụ (dành cho OS X 10.10) tại github.com/dinosec/iphone-dataprotection . Nó hoạt động trên OS X 10.11.5.
Aaron Brager

2
Nếu bạn cập nhật mã, bạn sẽ gần với một vị thần đối với tôi!
Jonas Zaugg

3
@JonasZaugg Tôi đã cập nhật mã mẫu cho iOS 10. Tôi hy vọng bạn thấy nó hữu ích.
andrewdotn

6

Xin lỗi, nhưng nó thậm chí có thể phức tạp hơn, liên quan đến pbkdf2 hoặc thậm chí là một biến thể của nó. Nghe WWDC 2010 phiên # 209, chủ yếu nói về các biện pháp bảo mật trong iOS 4, nhưng cũng đề cập ngắn gọn về mã hóa riêng biệt của các bản sao lưu và cách chúng liên quan.

Bạn có thể chắc chắn rằng nếu không biết mật khẩu, không có cách nào bạn có thể giải mã nó, ngay cả bằng vũ lực.

Giả sử bạn muốn cố gắng cho phép những người BIẾT mật khẩu truy cập vào dữ liệu sao lưu của họ.

Tôi sợ rằng không có cách nào xung quanh việc nhìn vào mã thực tế trong iTunes để tìm ra những bí danh nào được sử dụng.

Quay lại thời Newton, tôi phải giải mã dữ liệu từ một chương trình và có thể gọi trực tiếp chức năng giải mã của nó (tất nhiên là biết mật khẩu) mà không cần phải nhấn mạnh thuật toán của nó. Nó không còn dễ dàng nữa, thật không may.

Tôi chắc rằng xung quanh có những người có kỹ năng có thể thiết kế ngược mã iTunes đó - bạn chỉ cần khiến họ quan tâm.

Về lý thuyết, các bí danh của Apple nên được thiết kế theo cách làm cho dữ liệu vẫn an toàn (tức là trên thực tế không thể phá vỡ bằng các phương pháp vũ phu) cho bất kỳ kẻ tấn công nào biết phương pháp mã hóa chính xác. Và trong phiên WWDC 209, họ đã đi khá sâu vào chi tiết về những gì họ làm để đạt được điều này. Có lẽ bạn thực sự có thể nhận được câu trả lời trực tiếp từ đội bảo mật của Apple nếu bạn nói với họ ý định tốt của bạn. Rốt cuộc, ngay cả họ cũng nên biết rằng bảo mật bằng cách giải mã không thực sự hiệu quả. Hãy thử danh sách gửi thư bảo mật của họ. Ngay cả khi họ không trả lời, có thể một người khác âm thầm trong danh sách sẽ trả lời với một số trợ giúp.

Chúc may mắn!


1

Chưa thử, nhưng Elcomsoft đã phát hành một sản phẩm mà họ cho rằng có khả năng giải mã các bản sao lưu, cho các mục đích pháp y. Có thể không thú vị bằng việc tự thiết kế một giải pháp, nhưng nó có thể nhanh hơn.

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


1
Cảm ơn. Điều này không giải mã các bản sao lưu như vậy: nó chỉ bẻ khóa các phím. Tôi biết cách làm điều đó rồi ... và điều đó đơn giản hơn rất nhiều so với việc giải mã bản sao lưu khi bạn có khóa.
Aidan Fitzpatrick

-3

Bạn nên lấy một bản sao tiện ích dòng lệnh mdhelper của Erica Sadun ( OS X nhị phân & nguồn ). Nó hỗ trợ liệt kê và trích xuất nội dung của các bản sao lưu iPhone / iPod Touch, bao gồm sổ địa chỉ & cơ sở dữ liệu SMS, siêu dữ liệu và cài đặt ứng dụng khác.


1
Đó chỉ là một độc giả của PList: Tôi đã có thể làm công việc đó một cách tự nhiên. Nó không hỗ trợ các bản sao lưu được mã hóa, thứ mà tôi đang theo đuổi và nằm ngoài phạm vi của tiện ích đó.
Aidan Fitzpatrick

Bạn đã dành thời gian để thử các tiện ích? Các bản sao lưu của tôi được mã hóa và nó thực hiện chính xác những gì bạn đang cố gắng thực hiện.
Nathan de Vries

10
Có, và tôi cũng đã đọc nguồn. Nó không xử lý các bản sao lưu được mã hóa và đã được sửa đổi lần cuối trước khi phát hành hỗ trợ của iTunes cho các bản sao lưu được mã hóa. Tôi nghi ngờ bạn có nghĩa là các bản sao lưu của bạn được mã hóa hoặc iPhone của bạn sử dụng hệ thống tệp được mã hóa, đây hoàn toàn là một vấn đề khác. Cũng như không có hỗ trợ mã hóa trong mã, rõ ràng hơn là không có tùy chọn để chuyển mật khẩu trong các tùy chọn dòng lệnh. Và mã không sử dụng bất kỳ chứng chỉ hoặc móc khóa nào. Tôi rất muốn được chứng minh là sai về điều này, nhưng tôi thực sự không nghĩ là mình đúng! Tôi đánh giá cao đề nghị, mặc dù.
Aidan Fitzpatrick
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.