如何解密encryption的苹果iTunes iPhone备份?

许多不幸的iPhone用户已经问过我,帮助他们从iTunes备份中恢复数据。 当它们是未encryption的时候,这很容易,但是当它们被encryption时,不pipe密码是否已知。

因此,我试图找出encryption时在mddata和mdinfo文件上使用的encryptionscheme。 否则,我没有任何问题阅读这些文件,并build立了一些强大的C#库来做到这一点。 (如果你能帮忙,我不在乎你用哪种语言,这是我在这之后的原则!)

苹果公司的“iPhone OS企业部署指南”指出:“通过在iTunes的设备摘要窗格中selectencryptioniPhone备份选项,可以以encryption格式存储设备备份,文件使用AES128加256位密钥进行encryption。安全地存储在iPhone钥匙串中“。

这是一个很好的线索,在这里有关于iPhone上的Stackoverflow的一些很好的信息AES / Rijndael互操作性build议可以使用128和CBC模式的密钥大小。

除了任何其他混淆之外,还需要一个密钥和初始化向量(IV)/盐。

有人可能会认为,密钥是对“备份密码”的操纵,用户被iTunes提示input并传递给“C 苹果移动备份”,按照CBC规定的方式填充。 但是,鉴于对iPhone钥匙串的引用,我想知道“备份密码”是否可能不被用作X509证书或对称私钥的密码,并且证书或私钥本身可能被用作密钥。 ( AES和iTunesencryption/解密过程是对称的。)

IV是另一回事,可能是一些事情。 也许这是硬编码到iTunes或者设备本身的关键之一 。

尽pipe上面的苹果的评论暗示了设备钥匙链上存在的关键,但我认为这并不重要。 可以将encryption的备份恢复到不同的设备,这意味着与解密有关的所有信息都存在于备份和iTunesconfiguration中,并且在这种情况下,任何单独在设备上的任何内容都是不相关的和可replace的。 那么关键在哪里呢?

我已经从Windows机器上列出了下面的path,但是我们使用的操作系统非常多。

“\ appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml”包含一个带有“Keychain”字典条目的PList。 “\ programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist”包含一个具有“DeviceCertificate”,“HostCertificate”和“RootCertificate”的PList,所有这些看起来都是有效的X509证书。 相同的文件也似乎包含不对称的密钥“RootPrivateKey”和“HostPrivateKey”(我的阅读表明这些可能是PKCS#7-enveloped)。 此外,在每个备份中,Manifest.plist文件中都有“AuthSignature”和“AuthData”值,尽pipe这些值在每个文件逐渐备份后都会随之旋转,但build议将它们用作关键字,除非真正有用相当的参与正在完成。

这里有很多误导的东西,暗示从encryption的备份中获取数据很容易。 这不是,据我所知还没有完成。 绕过或禁用备份encryption完全是另一回事,而不是我想要做的。

这不是要破解iPhone或类似的东西。 我之后的所有内容都是从encryption的iTunes备份中提取数据(照片,联系人等)的手段,因为我可以将其encryption。 我已经尝试了各种排列与我放在上面的信息,但没有任何地方。 我会很感激任何想法或技巧,我可能错过了。

安全研究人员Jean-BaptisteBédrune和Jean Sigwald 介绍了如何在2011年阿姆斯特丹的Hack-in-the-box 上做到这一点 。

从那以后,苹果公司发布了一个iOS安全白皮书 ,详细介绍了密钥和algorithm,Charlie Miller等人 已经发布了iOS黑客手册 ,其中涵盖了一些相同的基础,在一个怎样的时尚。 当iOS 10第一次出现时,苹果没有公布的备份格式发生了变化,但是不同的人反向devise了格式的变化 。

encryption的备份是伟大的

关于encryptioniPhone备份的好处是,它们包含了诸如WiFi密码之类的东西,而这些密码并不是经常未encryption的备份。 正如在iOS安全白皮书中所讨论的那样,encryption的备份被认为更“安全”,所以苹果公司认为可以在其中包含更多的敏感信息。

一个重要的警告:显然,解密您的iOS设备的备份将删除其encryption。 为了保护您的隐私和安全, 您只能在具有全盘encryptionfunction的计算机上运行这些脚本。 虽然安全专家可以编写保护内存中的密钥的软件,例如使用VirtualLock()SecureZeroMemory()等函数,但是这些Python脚本会将encryption密钥和密码存储在string中,由Python收集。 这意味着你的秘密密钥和密码将在RAM中生存一段时间,从它们将泄漏到你的交换文件和你的磁盘,在那里对手可以恢复它们。 这完全违背了encryption备份的要点。

如何解密备份:理论上

iOS安全白皮书比我更好地解释了每个文件密钥,保护级别,保护级别密钥和密钥包的基本概念。 如果您还不熟悉这些,请花几分钟时间阅读相关部分。

现在您知道iOS中的每个文件都使用自己的随机每个文件encryption密钥进行encryption,属于一个保护类,并且每个文件的encryption密钥都存储在文件系统元数据中,并保存在保护类密钥中。

解密:

  1. 解码存储在Manifest.plistBackupKeyBag条目中的BackupKeyBag 。 白皮书给出了这种结构的高级概述。 iPhone Wiki描述了二进制格式:一个4字节的stringtypes字段,一个4字节的big-endian长度字段,然后是值本身。

    重要的值是PBKDF2 ITERSALT ,双重保护盐DPSL和迭代计数DPIC ,然后对每个保护CLSWPKY包装密钥。

  2. 使用备份密码使用正确的PBKDF2盐和迭代次数派生出一个32字节的密钥。 首先用DPSLDPIC使用SHA256,然后用ITERSALT使用SHA1。

    根据RFC 3394打开每个包装的密钥。

  3. 通过从ManifestKey中的Manifest.plist拉出4字节的保护类和更长的密钥来解密清单数据库,然后展开它。 你现在有一个包含所有文件元数据的SQLite数据库。

  4. 对于每个感兴趣的文件,通过在Files.file数据库列中查找包含EncryptionKeyProtectionClass条目的二进制plist来获取类encryption的每个文件的encryption密钥和保护类代码。 使用前从EncryptionKey剥离最初的四字节长度标签。

    然后,通过用用备份密码解开的类密钥解开它来导出最终的解密密钥。 然后使用AES在CBC模式下以零IV解密文件。

如何解密备份:在实践中

在可运行的源代码forms中,以下是如何从encryption的iPhone备份中解密计算器首选项文件:

 #!/usr/bin/env python2.7 # coding: UTF-8 import argparse import base64 import getpass import hashlib import os.path import pprint import random import shutil import sqlite3 import stat import string import struct import sys import tempfile import Crypto.Cipher.AES # https://www.dlitz.net/software/pycrypto/ import biplist import fastpbkdf2 def main(): ## Parse options parser = argparse.ArgumentParser() parser.add_argument('--backup-directory', dest='backup_directory', default='data/encrypted') parser.add_argument('--password-pipe', dest='password_pipe', help="""\ Keeps password from being visible in system process list. Typical use: --password-pipe=<(echo -n foo) """) parser.add_argument('--no-anonymize-output', dest='anonymize', action='store_false') parser.add_argument('--base64-passcode-key-pipe', dest='passcode_key_pipe', help="""\ Provide a previously derived passcode key to save time doing PBDKF2 when developing""") args = parser.parse_args() global ANONYMIZE_OUTPUT ANONYMIZE_OUTPUT = args.anonymize if ANONYMIZE_OUTPUT: print 'Warning: All output keys are FAKE to protect your privacy' manifest_file = os.path.join(args.backup_directory, 'Manifest.plist') with open(manifest_file, 'rb') as infile: manifest_plist = biplist.readPlist(infile) keybag = Keybag(manifest_plist['BackupKeyBag']) # the actual keys are unknown, but the wrapped keys are known keybag.printClassKeys() if args.password_pipe: password = readpipe(args.password_pipe) else: password = getpass.getpass('Backup password: ') if args.passcode_key_pipe: passcode_key = base64.decodestring(readpipe(args.passcode_key_pipe)) else: passcode_key = None ## Unlock keybag with password if not keybag.unlockWithPasscode(password, passcode_key): raise Exception('Could not unlock keybag; bad password?') # now the keys are known too keybag.printClassKeys() ## Decrypt metadata DB manifest_key = manifest_plist['ManifestKey'][4:] with open(os.path.join(args.backup_directory, 'Manifest.db'), 'r') as db: encrypted_db = db.read() manifest_class = struct.unpack('<l', manifest_plist['ManifestKey'][:4])[0] key = keybag.unwrapKeyForClass(manifest_class, manifest_key) decrypted_data = AESdecryptCBC(encrypted_db, key) temp_dir = tempfile.mkdtemp() try: # Does anyone know how to get Python's SQLite module to open some # bytes in memory as a database? db_filename = os.path.join(temp_dir, 'db.sqlite3') with open(db_filename, 'w') as db_file: db_file.write(decrypted_data) conn = sqlite3.connect(db_filename) c = conn.cursor() c.execute(""" SELECT fileID, domain, relativePath, file FROM Files WHERE relativePath LIKE '%/Preferences/com.apple.calculator.plist' ORDER BY relativePath""") results = c.fetchall() finally: shutil.rmtree(temp_dir) for item in results: fileID, domain, relativePath, file_bplist = item plist = biplist.readPlistFromString(file_bplist) file_data = plist['$objects'][plist['$top']['root'].integer] size = file_data['Size'] protection_class = file_data['ProtectionClass'] encryption_key = plist['$objects'][ file_data['EncryptionKey'].integer]['NS.data'][4:] backup_filename = os.path.join(args.backup_directory, fileID[:2], fileID) with open(backup_filename, 'rb') as infile: data = infile.read() key = keybag.unwrapKeyForClass(protection_class, encryption_key) # truncate to actual length, as encryption may introduce padding decrypted_data = AESdecryptCBC(data, key)[:size] print '== decrypted data:' print wrap(decrypted_data) print print '== pretty-printed calculator preferences' pprint.pprint(biplist.readPlistFromString(decrypted_data)) ## # this section is mostly copied from parts of iphone-dataprotection # http://code.google.com/p/iphone-dataprotection/ CLASSKEY_TAGS = ["CLAS","WRAP","WPKY", "KTYP", "PBKY"] #UUID KEYBAG_TYPES = ["System", "Backup", "Escrow", "OTA (icloud)"] KEY_TYPES = ["AES", "Curve25519"] PROTECTION_CLASSES={ 1:"NSFileProtectionComplete", 2:"NSFileProtectionCompleteUnlessOpen", 3:"NSFileProtectionCompleteUntilFirstUserAuthentication", 4:"NSFileProtectionNone", 5:"NSFileProtectionRecovery?", 6: "kSecAttrAccessibleWhenUnlocked", 7: "kSecAttrAccessibleAfterFirstUnlock", 8: "kSecAttrAccessibleAlways", 9: "kSecAttrAccessibleWhenUnlockedThisDeviceOnly", 10: "kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly", 11: "kSecAttrAccessibleAlwaysThisDeviceOnly" } WRAP_DEVICE = 1 WRAP_PASSCODE = 2 class Keybag(object): def __init__(self, data): self.type = None self.uuid = None self.wrap = None self.deviceKey = None self.attrs = {} self.classKeys = {} self.KeyBagKeys = None #DATASIGN blob self.parseBinaryBlob(data) def parseBinaryBlob(self, data): currentClassKey = None for tag, data in loopTLVBlocks(data): if len(data) == 4: data = struct.unpack(">L", data)[0] if tag == "TYPE": self.type = data if self.type > 3: print "FAIL: keybag type > 3 : %d" % self.type elif tag == "UUID" and self.uuid is None: self.uuid = data elif tag == "WRAP" and self.wrap is None: self.wrap = data elif tag == "UUID": if currentClassKey: self.classKeys[currentClassKey["CLAS"]] = currentClassKey currentClassKey = {"UUID": data} elif tag in CLASSKEY_TAGS: currentClassKey[tag] = data else: self.attrs[tag] = data if currentClassKey: self.classKeys[currentClassKey["CLAS"]] = currentClassKey def unlockWithPasscode(self, passcode, passcode_key=None): if passcode_key is None: passcode1 = fastpbkdf2.pbkdf2_hmac('sha256', passcode, self.attrs["DPSL"], self.attrs["DPIC"], 32) passcode_key = fastpbkdf2.pbkdf2_hmac('sha1', passcode1, self.attrs["SALT"], self.attrs["ITER"], 32) print '== Passcode key' print base64.encodestring(anonymize(passcode_key)) for classkey in self.classKeys.values(): if not classkey.has_key("WPKY"): continue k = classkey["WPKY"] if classkey["WRAP"] & WRAP_PASSCODE: k = AESUnwrap(passcode_key, classkey["WPKY"]) if not k: return False classkey["KEY"] = k return True def unwrapKeyForClass(self, protection_class, persistent_key): ck = self.classKeys[protection_class]["KEY"] if len(persistent_key) != 0x28: raise Exception("Invalid key length") return AESUnwrap(ck, persistent_key) def printClassKeys(self): print "== Keybag" print "Keybag type: %s keybag (%d)" % (KEYBAG_TYPES[self.type], self.type) print "Keybag version: %d" % self.attrs["VERS"] print "Keybag UUID: %s" % anonymize(self.uuid.encode("hex")) print "-"*209 print "".join(["Class".ljust(53), "WRAP".ljust(5), "Type".ljust(11), "Key".ljust(65), "WPKY".ljust(65), "Public key"]) print "-"*208 for k, ck in self.classKeys.items(): if k == 6: print "" print "".join( [PROTECTION_CLASSES.get(k).ljust(53), str(ck.get("WRAP","")).ljust(5), KEY_TYPES[ck.get("KTYP",0)].ljust(11), anonymize(ck.get("KEY", "").encode("hex")).ljust(65), anonymize(ck.get("WPKY", "").encode("hex")).ljust(65), ck.get("PBKY", "").encode("hex")]) print def loopTLVBlocks(blob): i = 0 while i + 8 <= len(blob): tag = blob[i:i+4] length = struct.unpack(">L",blob[i+4:i+8])[0] data = blob[i+8:i+8+length] yield (tag,data) i += 8 + length def unpack64bit(s): return struct.unpack(">Q",s)[0] def pack64bit(s): return struct.pack(">Q",s) def AESUnwrap(kek, wrapped): C = [] for i in xrange(len(wrapped)/8): C.append(unpack64bit(wrapped[i*8:i*8+8])) n = len(C) - 1 R = [0] * (n+1) A = C[0] for i in xrange(1,n+1): R[i] = C[i] for j in reversed(xrange(0,6)): for i in reversed(xrange(1,n+1)): todec = pack64bit(A ^ (n*j+i)) todec += pack64bit(R[i]) B = Crypto.Cipher.AES.new(kek).decrypt(todec) A = unpack64bit(B[:8]) R[i] = unpack64bit(B[8:]) if A != 0xa6a6a6a6a6a6a6a6: return None res = "".join(map(pack64bit, R[1:])) return res ZEROIV = "\x00"*16 def AESdecryptCBC(data, key, iv=ZEROIV, padding=False): if len(data) % 16: print "AESdecryptCBC: data length not /16, truncating" data = data[0:(len(data)/16) * 16] data = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, iv).decrypt(data) if padding: return removePadding(16, data) return data ## # here are some utility functions, one making sure I don't leak my # secret keys when posting the output on Stack Exchange anon_random = random.Random(0) memo = {} def anonymize(s): global anon_random, memo if ANONYMIZE_OUTPUT: if s in memo: return memo[s] possible_alphabets = [ string.digits, string.digits + 'abcdef', string.letters, "".join(chr(x) for x in range(0, 256)), ] for a in possible_alphabets: if all(c in a for c in s): alphabet = a break ret = "".join([anon_random.choice(alphabet) for i in range(len(s))]) memo[s] = ret return ret else: return s def wrap(s, width=78): "Return a width-wrapped repr(s)-like string without breaking on \'s" s = repr(s) quote = s[0] s = s[1:-1] ret = [] while len(s): i = s.rfind('\\', 0, width) if i <= width - 4: # "\x??" is four characters i = width ret.append(s[:i]) s = s[i:] return '\n'.join("%s%s%s" % (quote, line ,quote) for line in ret) def readpipe(path): if stat.S_ISFIFO(os.stat(path).st_mode): with open(path, 'rb') as pipe: return pipe.read() else: raise Exception("Not a pipe: {!r}".format(path)) if __name__ == '__main__': main() 

然后打印这个输出:

 Warning: All output keys are FAKE to protect your privacy == Keybag Keybag type: Backup keybag (1) Keybag version: 3 Keybag UUID: dc6486c479e84c94efce4bea7169ef7d ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Class WRAP Type Key WPKY Public key ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- NSFileProtectionComplete 2 AES 4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceedee86b4cde9f97afec197ad3b13c5d12b NSFileProtectionCompleteUnlessOpen 2 AES 09e8a0a9965f00f213ce06143a52801f35bde2af0ad54972769845d480b5043f545fa9b66a0353a6 NSFileProtectionCompleteUntilFirstUserAuthentication 2 AES e966b6a0742878ce747cec3fa1bf6a53b0d811ad4f1d6147cd28a5d400a8ffe0bbabea5839025cb5 NSFileProtectionNone 2 AES 902f46847302816561e7df57b64beea6fa11b0068779a65f4c651dbe7a1630f323682ff26ae7e577 NSFileProtectionRecovery? 3 AES a3935fed024cd9bc11d0300d522af8e89accfbe389d7c69dca02841df46c0a24d0067dba2f696072 kSecAttrAccessibleWhenUnlocked 2 AES 09a1856c7e97a51a9c2ecedac8c3c7c7c10e7efa931decb64169ee61cb07a0efb115050fd1e33af1 kSecAttrAccessibleAfterFirstUnlock 2 AES 0509d215f2f574efa2f192efc53c460201168b26a175f066b5347fc48bc76c637e27a730b904ca82 kSecAttrAccessibleAlways 2 AES b7ac3c4f1e04896144ce90c4583e26489a86a6cc45a2b692a5767b5a04b0907e081daba009fdbb3c kSecAttrAccessibleWhenUnlockedThisDeviceOnly 3 AES 417526e67b82e7c6c633f9063120a299b84e57a8ffee97b34020a2caf6e751ec5750053833ab4d45 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 3 AES b0e17b0cf7111c6e716cd0272de5684834798431c1b34bab8d1a1b5aba3d38a3a42c859026f81ccc kSecAttrAccessibleAlwaysThisDeviceOnly 3 AES 9b3bdc59ae1d85703aa7f75d49bdc600bf57ba4a458b20a003a10f6e36525fb6648ba70e6602d8b2 == Passcode key VNfSPwXOK8mvKxTtmZ51JppAzrsG7gkWSiY8W7xnRX4= == Keybag Keybag type: Backup keybag (1) Keybag version: 3 Keybag UUID: dc6486c479e84c94efce4bea7169ef7d ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Class WRAP Type Key WPKY Public key ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- NSFileProtectionComplete 2 AES 64e8fc94a7b670b0a9c4a385ff395fe9ba5ee5b0d9f5a5c9f0202ef7fdcb386f 4c80b6da07d35d393fc7158e18b8d8f9979694329a71ceedee86b4cde9f97afec197ad3b13c5d12b NSFileProtectionCompleteUnlessOpen 2 AES 22a218c9c446fbf88f3ccdc2ae95f869c308faaa7b3e4fe17b78cbf2eeaf4ec9 09e8a0a9965f00f213ce06143a52801f35bde2af0ad54972769845d480b5043f545fa9b66a0353a6 NSFileProtectionCompleteUntilFirstUserAuthentication 2 AES 1004c6ca6e07d2b507809503180edf5efc4a9640227ac0d08baf5918d34b44ef e966b6a0742878ce747cec3fa1bf6a53b0d811ad4f1d6147cd28a5d400a8ffe0bbabea5839025cb5 NSFileProtectionNone 2 AES 2e809a0cd1a73725a788d5d1657d8fd150b0e360460cb5d105eca9c60c365152 902f46847302816561e7df57b64beea6fa11b0068779a65f4c651dbe7a1630f323682ff26ae7e577 NSFileProtectionRecovery? 3 AES 9a078d710dcd4a1d5f70ea4062822ea3e9f7ea034233e7e290e06cf0d80c19ca a3935fed024cd9bc11d0300d522af8e89accfbe389d7c69dca02841df46c0a24d0067dba2f696072 kSecAttrAccessibleWhenUnlocked 2 AES 606e5328816af66736a69dfe5097305cf1e0b06d6eb92569f48e5acac3f294a4 09a1856c7e97a51a9c2ecedac8c3c7c7c10e7efa931decb64169ee61cb07a0efb115050fd1e33af1 kSecAttrAccessibleAfterFirstUnlock 2 AES 6a4b5292661bac882338d5ebb51fd6de585befb4ef5f8ffda209be8ba3af1b96 0509d215f2f574efa2f192efc53c460201168b26a175f066b5347fc48bc76c637e27a730b904ca82 kSecAttrAccessibleAlways 2 AES c0ed717947ce8d1de2dde893b6026e9ee1958771d7a7282dd2116f84312c2dd2 b7ac3c4f1e04896144ce90c4583e26489a86a6cc45a2b692a5767b5a04b0907e081daba009fdbb3c kSecAttrAccessibleWhenUnlockedThisDeviceOnly 3 AES 80d8c7be8d5103d437f8519356c3eb7e562c687a5e656cfd747532f71668ff99 417526e67b82e7c6c633f9063120a299b84e57a8ffee97b34020a2caf6e751ec5750053833ab4d45 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 3 AES a875a15e3ff901351c5306019e3b30ed123e6c66c949bdaa91fb4b9a69a3811e b0e17b0cf7111c6e716cd0272de5684834798431c1b34bab8d1a1b5aba3d38a3a42c859026f81ccc kSecAttrAccessibleAlwaysThisDeviceOnly 3 AES 1e7756695d337e0b06c764734a9ef8148af20dcc7a636ccfea8b2eb96a9e9373 9b3bdc59ae1d85703aa7f75d49bdc600bf57ba4a458b20a003a10f6e36525fb6648ba70e6602d8b2 == decrypted data: 'bplist00\xd3\x01\x02\x03\x04\x05\x06\\DisplayValue[MemoryValue_\x10\x14Trigono' 'metricModeKey_\x10%3.14159265358979323846264338327950288_\x10#2.71828182845904' '5235360287471352662\x08\x08\x0f\x1c(?g\x8d\x00\x00\x00\x00\x00\x00\x01\x01\x00' '\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x8e' == pretty-printed calculator preferences {'DisplayValue': '3.14159265358979323846264338327950288', 'MemoryValue': '2.718281828459045235360287471352662', 'TrigonometricModeKey': False} 

额外的信用

Bédrune和Sigwald发布的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的手机进行备份,但并不是所有这些都改变了…如果您想要我更新上面的代码以转储出保存的密码,请留下评论; P

对不起,但它可能更复杂,涉及pbkdf2,甚至是它的一个变种。 听听WWDC 2010会议#209,主要讨论iOS 4中的安全措施,还简要提及备份的单独encryption以及它们之间的关系。

如果不知道密码,你可以确信,即使通过暴力破解,也无法解密密码。

假设您想要让知道密码的人能够访问其备份的数据。

我担心没有办法在iTunes中查看实际的代码,以确定使用哪种algorithm。

回到牛顿时代,我不得不解密程序中的数据,并能直接调用它的解密函数(当然知道密码),而不需要甚至忽略它的algorithm。 不幸的是,这并不容易。

我相信周围有技术熟练的人可以对iTunes代码进行反向工程 – 只需要让他们感兴趣即可。

理论上讲,苹果的algorithm应该devise成能够使数据安全(即通过powershell方法实际上是不可破解的)到任何知道确切encryption方法的攻击者。 在WWDC209会议中,他们深入细节地介绍了他们如何做到这一点。 如果你告诉他们你的好意,也许你可以直接从苹果的安全团队获得答案。 毕竟,即使他们应该知道,混淆的安全性并不是真的有效。 试试他们的安全邮件列表。 即使他们没有回应,也许在名单上默默的人会回应一些帮助。

祝你好运!

还没有尝试过,但Elcomsoft发布了他们声称能够解密备份的产品,用于取证目的。 也许不如自己devise解决scheme那么酷,但速度可能会更快。

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

你应该抓取Erica Sadun的mdhelper命令行工具( OS X binary & source )的副本。 它支持列出和提取iPhone / iPod Touch备份的内容,包括地址簿和SMS数据库,以及其他应用程序元数据和设置。