Несколько несчастных пользователей iPhone попросили меня помочь им восстановить данные из резервных копий iTunes. Это легко сделать, когда они не зашифрованы, но не когда они зашифрованы, вне зависимости от того, известен пароль или нет.
Таким образом, я пытаюсь выяснить схему шифрования, используемую для файлов mddata и mdinfo при шифровании. В противном случае у меня нет проблем с чтением этих файлов, и я создал для этого несколько надежных библиотек C #. (Если вы можете помочь, меня не волнует, на каком языке вы говорите. Это тот принцип, который мне нужен!)
В «Руководстве по развертыванию корпоративной операционной системы iPhone» от Apple указано, что «резервные копии устройств можно хранить в зашифрованном формате, выбрав параметр« Зашифровать резервную копию iPhone »на панели сводки устройства iTunes. Файлы зашифрованы с использованием AES128 с 256-битным ключом. Ключ надежно хранится в связке ключей iPhone ".
Это довольно хорошая подсказка, и здесь есть полезная информация о Stackoverflow на iPhone о совместимости AES / Rijndael, предполагающая, что размер ключа 128 и может использоваться режим CBC.
Помимо любой другой обфускации, требуются ключ и вектор инициализации (IV) / соль.
Можно предположить, что ключ представляет собой манипуляцию с «резервным паролем», который iTunes предлагает пользователям ввести и передает в « AppleMobileBackup.exe », дополненный способом, продиктованным CBC. Однако, учитывая ссылку на связку ключей iPhone, мне интересно, нельзя ли использовать «резервный пароль» в качестве пароля для сертификата X509 или симметричного закрытого ключа, и что сам сертификат или закрытый ключ может использоваться как ключ. ( Процесс шифрования / дешифрования AES и iTunes является симметричным.)
IV - другое дело, и это могло быть несколько вещей. Возможно, это один из ключей, жестко закодированных в iTunes или в самих устройствах .
Хотя приведенный выше комментарий Apple предполагает, что ключ присутствует на связке ключей устройства, я думаю, что это не так важно. Можно восстановить зашифрованную резервную копию на другое устройство, что предполагает, что вся информация, относящаяся к расшифровке, присутствует в резервной копии и конфигурации iTunes, и что все, что находится исключительно на устройстве, не имеет отношения к делу и заменяется в этом контексте. Так где же может быть ключ?
Я перечислил ниже пути с компьютера с Windows, но по большей части это зависит от того, какую ОС мы используем.
«\ Appdata \ Roaming \ Apple Computer \ iTunes \ itunesprefs.xml» содержит PList с записью dict «Связка ключей». «\ Programdata \ apple \ Lockdown \ 09037027da8f4bdefdea97d706703ca034c88bab.plist» содержит PList с «DeviceCertificate», «HostCertificate» и «RootCertificate», все из которых являются действительными сертификатами X509. В том же файле также содержатся асимметричные ключи «RootPrivateKey» и «HostPrivateKey» (согласно моим прочтениям, это может быть оболочка PKCS # 7). Кроме того, в каждой резервной копии есть значения «AuthSignature» и «AuthData» в файле Manifest.plist, хотя они, похоже, меняются по мере того, как каждый файл создается инкрементным резервным копированием, предполагая, что они не так полезны в качестве ключа, если что-то действительно довольно сложно делается.
Существует множество вводящих в заблуждение материалов, предполагающих, что получить данные из зашифрованных резервных копий легко. Это не так, и, насколько мне известно, этого не было. Обход или отключение шифрования резервных копий - это совсем другое дело, и я не собираюсь этого делать.
Речь не о том, чтобы взломать iPhone или что-то в этом роде. Все, что мне нужно, это средство для извлечения данных (фотографий, контактов и т. Д.) Из зашифрованных резервных копий iTunes, как я могу использовать незашифрованные. Я пробовал всевозможные перестановки с информацией, которую изложил выше, но ничего не добился. Буду признателен за любые мысли или приемы, которые я мог пропустить.
источник
Ответы:
Исследователи безопасности Жан-Батист Бедрун и Жан Сигвальд представили, как это сделать, на Hack-in-the-box Amsterdam 2011 .
С тех пор Apple выпустила технический документ по безопасности iOS с более подробной информацией о ключах и алгоритмах, а Чарли Миллер и др. выпустили руководство iOS Hacker's Handbook , в котором рассматриваются некоторые из тех же вопросов в виде практических рекомендаций. Когда впервые вышла iOS 10, в формат резервного копирования были внесены изменения, которые Apple сначала не публиковала, но разные люди перепроектировали изменения формата .
Зашифрованные резервные копии великолепны
Самое замечательное в зашифрованных резервных копиях iPhone заключается в том, что они содержат такие вещи, как пароли WiFi, которых нет в обычных незашифрованных резервных копиях. Как обсуждалось в техническом документе по безопасности iOS , зашифрованные резервные копии считаются более «безопасными», поэтому Apple считает правильным включать в них более конфиденциальную информацию.
Важное предупреждение: очевидно, что расшифровка резервной копии вашего устройства iOS удаляет ее шифрование. Чтобы защитить вашу конфиденциальность и безопасность, вы должны запускать эти сценарии только на машине с полным шифрованием диска. Хотя эксперт по безопасности может написать программное обеспечение, которое защищает ключи в памяти, например, используя такие функции
VirtualLock()
иSecureZeroMemory()
многое другое, эти сценарии Python будут хранить ваши ключи шифрования и пароли в строках, которые будут собираться Python для сбора мусора. Это означает, что ваши секретные ключи и пароли какое-то время будут храниться в ОЗУ, откуда они попадут в ваш файл подкачки и на ваш диск, где злоумышленник сможет их восстановить. Это полностью лишает смысла иметь зашифрованную резервную копию.Как расшифровать резервные копии: в теории
IOS Security Whitepaper объясняет основные концепции каждого файла ключей, классов защиты, ключи класса защиты, и keybags лучше , чем я могу. Если вы еще не знакомы с ними, найдите несколько минут, чтобы прочитать соответствующие части.
Теперь вы знаете, что каждый файл в iOS зашифрован своим собственным случайным ключом шифрования для каждого файла, принадлежит к классу защиты, а ключи шифрования для каждого файла хранятся в метаданных файловой системы, заключенных в ключ класса защиты.
Чтобы расшифровать:
Расшифруйте сумку с ключами, хранящуюся в
BackupKeyBag
записиManifest.plist
. Общий обзор этой структуры дан в техническом документе . В iPhone Wiki описан двоичный формат: 4-байтовое поле строкового типа, 4-байтовое поле длины с прямым порядком байтов, а затем само значение.Важные значения являются PBKDF2
ITER
ations иSALT
, соль двойной защитыDPSL
и итерация рассчитыватьDPIC
, а затем для каждой защитыCLS
, наWPKY
обернутом ключе.Используя резервный пароль, получите 32-байтовый ключ, используя правильную соль PBKDF2 и количество итераций. Сначала используйте раунд SHA256 с
DPSL
иDPIC
, затем раунд SHA1 сITER
иSALT
.Разверните каждый завернутый ключ в соответствии с RFC 3394 .
Расшифровать манифест базы данных, потянув класс защиты 4-байтовой и более длинный ключ от
ManifestKey
дюймаManifest.plist
, и разворачивает его. Теперь у вас есть база данных SQLite со всеми метаданными файлов.Для каждого файла , представляющего интереса, получить для каждого файла шифрование коды ключа и класс защиты класса шифруется , глядя в
Files.file
столбце базы данных для бинарного PLIST , содержащегоEncryptionKey
иProtectionClass
записей. Удалите исходный тег длиной четыре байтаEncryptionKey
перед использованием.Затем получите окончательный ключ дешифрования, развернув его с помощью ключа класса, который был развернут с резервным паролем. Затем расшифруйте файл с помощью AES в режиме CBC с нулевым IV.
Как расшифровать резервные копии: на практике
Сначала вам понадобятся некоторые зависимости библиотеки. Если вы используете 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, опубликованный Бедруном и Зигвальдом, может расшифровать связку ключей из резервной копии, включая такие забавные вещи, как сохраненные пароли Wi-Fi и веб-сайтов:
Этот код больше не работает с резервными копиями с телефонов с последней версией iOS, но есть некоторые порты golang , которые были обновлены, что позволяет получить доступ к связке ключей .
источник
pip install --user pycrypto
Спасибо!Извините, но это может быть даже сложнее, включая pbkdf2 или даже его вариант. Послушайте сессию № 209 WWDC 2010, в которой в основном рассказывается о мерах безопасности в iOS 4, но также вкратце упоминается отдельное шифрование резервных копий и их взаимосвязь.
Вы можете быть уверены, что, не зная пароля, вы не сможете его расшифровать даже с помощью грубой силы.
Предположим, вы хотите попытаться разрешить людям, ЗНАЮЩИМ пароль, получить доступ к данным их резервных копий.
Боюсь, что невозможно обойтись без фактического кода в iTunes, чтобы выяснить, какие алгоритмы используются.
Еще во времена Ньютона мне приходилось расшифровывать данные из программы, и я мог напрямую вызывать ее функцию дешифрования (конечно, зная пароль), даже не зная ее алгоритма. К сожалению, это уже не так просто.
Я уверен, что есть опытные люди, которые могут реконструировать этот код iTunes - вам просто нужно их заинтересовать.
Теоретически алгоритмы Apple должны быть спроектированы таким образом, чтобы данные оставались безопасными (т. Е. Практически не взломанными методами грубой силы) для любого злоумышленника, знающего точный метод шифрования. И в сеансе 209 WWDC они довольно подробно рассказали о том, что они делают для этого. Может быть, вы действительно сможете получить ответы непосредственно от службы безопасности Apple, если расскажете им о своих добрых намерениях. В конце концов, даже они должны знать, что защита с помощью обфускации не очень эффективна. Попробуйте их список рассылки по безопасности. Даже если они не ответят, может быть, кто-нибудь из списка молча ответит вам и предложит помощь.
Удачи!
источник
Не пробовал, но Elcomsoft выпустила продукт, который, по их утверждениям, способен расшифровывать резервные копии для целей криминалистики. Может быть, это не так круто, как разработать решение самостоятельно, но может быть быстрее.
http://www.elcomsoft.com/eppb.html
источник
Вам следует взять копию утилиты командной строки mdhelper Эрики Садун ( двоичный файл и исходный код OS X ). Он поддерживает перечисление и извлечение содержимого резервных копий iPhone / iPod Touch, включая базы данных адресной книги и SMS, а также другие метаданные и настройки приложений.
источник