암호화된 Apple iTunes iPhone 백업의 암호를 해독하는 방법은 무엇입니까?
많은 불행한 iPhone 사용자들로부터 iTunes 백업에서 데이터를 복구하는 것을 도와달라는 요청을 받았습니다.암호화되지 않은 경우에는 쉬워지지만 암호를 알고 있는지 여부에 관계없이 암호화되지는 않습니다.
그래서 저는 암호화 시 mddata와 mdinfo 파일에 사용되는 암호화 방식을 파악하려고 합니다.다른 방법으로 이 파일을 읽는 데 문제가 없으며, 이를 위해 강력한 C# 라이브러리를 구축했습니다. (도움이 된다면 어떤 언어를 사용하든 상관없습니다.)이것이 제가 추구하는 원칙입니다!)
Apple "iPhone OS Enterprise Deployment Guide"에는 "iTunes의 장치 요약 창에서 iPhone 백업 암호화 옵션을 선택하여 장치 백업을 암호화된 형식으로 저장할 수 있습니다.파일은 256비트 키로 AES128을 사용하여 암호화됩니다.키는 iPhone 키 체인에 안전하게 저장됩니다."
꽤 좋은 단서입니다. 아이폰 AES/Rijndael의 스택 오버플로에 대한 좋은 정보가 있습니다. 키 크기가 128이고 CBC 모드가 사용될 수 있음을 시사합니다.
다른 난독화 외에도 키와 초기화 벡터(IV)/salt가 필요합니다.
사용자가 iTunes에서 입력하라는 메시지를 받고 CBC에서 지시하는 방식으로 패딩된 "AppleMobileBackup.exe"로 전달되는 "백업 암호"를 조작한 것으로 가정할 수 있습니다.다만 아이폰 키체인에 대한 언급을 볼 때 X509 인증서나 대칭 개인 키에서 '백업 비밀번호'가 암호로 사용되지 않을 수도 있고, 인증서나 개인 키 자체가 키로 사용될 수도 있는지 궁금합니다(AES와 iTunes 암호화/암호 해독 프로세스는 대칭입니다).
링거 주사는 다른 문제이고, 몇 가지 문제일 수 있습니다.아마도 iTunes 또는 기기 자체에 하드 코딩된 키 중 하나일 것입니다.
위의 애플의 언급은 장치의 키 체인에 키가 있다는 것을 암시하지만, 저는 이것이 그렇게 중요하지 않다고 생각합니다.암호화된 백업을 다른 장치에 복원할 수 있습니다. 이는 암호 해독과 관련된 모든 정보가 백업 및 iTunes 구성에 존재하며 장치에만 있는 모든 정보는 이 컨텍스트에서 관련이 없으며 대체할 수 없음을 나타냅니다.그렇다면 열쇠는 어디에 있을까요?
아래에 Windows 컴퓨터의 경로를 나열했지만 어떤 OS를 사용하든 중요합니다.
"\appdata\Roaming\Apple Computer\iTunes\itunesprefs.xml"에는 "Keychain" 딕트 항목이 있는 PList가 포함되어 있습니다."\programdata\apple\"잠금 \09037027da8f4bdea97d706703ca034c88bab.plist"에는 "DeviceCertificate", "HostCertificate" 및 "RootCertificate"가 포함된 PList가 포함되어 있으며 모두 유효한 X509 인증서로 나타납니다.동일한 파일에 비대칭 키 "RootPrivateKey" 및 "HostPrivateKey"도 포함되어 있는 것으로 보입니다(제가 읽은 바에 따르면 이 키는 PKCS #7 엔벨로프일 수 있습니다).또한 각 백업 내에는 Manifest.plist 파일에 "AuthSignature" 및 "AuthData" 값이 있습니다. 이 값은 각 파일이 증분 백업됨에 따라 순환되는 것처럼 보이지만 실제로 관련된 작업이 수행되지 않는 한 키로 그다지 유용하지 않습니다.
암호화된 백업에서 데이터를 얻는 것이 쉽다는 오해의 소지가 있는 내용이 많이 있습니다.그렇지 않습니다. 제가 알기로는 아직 안 된 것 같습니다.백업 암호화를 우회하거나 비활성화하는 것은 전적으로 별개의 문제이며, 제가 하려는 것은 아닙니다.
이것은 아이폰을 해킹하거나 그런 것에 대한 것이 아닙니다.여기서 제가 원하는 것은 암호화된 iTunes 백업에서 데이터(사진, 연락처 등)를 추출하는 방법뿐입니다. 암호화된 iTunes 백업을 해제할 수 있기 때문입니다.위에 적어둔 정보로 온갖 종류의 순열을 시도했지만 아무 것도 얻지 못했습니다.제가 놓쳤을 수도 있는 어떤 생각이나 기술도 감사하겠습니다.
보안 연구원 Jean-Baptiste Bedrune와 Jean Sigwald는 Hack-in-the-box 2011에서 이를 수행하는 방법을 발표했습니다.
이후 애플은 키와 알고리즘, 찰리 밀러 등에 대한 자세한 내용이 담긴 iOS 보안 백서를 발표했습니다.iOS 해커 핸드북을 출시했습니다. 이 핸드북은 사용법 방식으로 동일한 분야를 다루고 있습니다.iOS 10이 처음 출시되었을 때 애플이 처음에 공개하지 않았던 백업 포맷에 대한 변경이 있었지만, 다양한 사람들이 포맷 변경을 리버스 엔지니어링했습니다.
암호화된 백업이 우수합니다.
암호화된 iPhone 백업의 장점은 일반적인 암호화되지 않은 백업에는 없는 WiFi 암호와 같은 것이 포함되어 있다는 것입니다.iOS 보안 백서에서 설명한 바와 같이, 암호화된 백업은 더 "보안"한 것으로 간주되므로 Apple은 이 백업에 더 중요한 정보를 포함해도 괜찮다고 생각합니다.
중요한 경고: iOS 기기의 백업 암호를 해독하면 암호화가 제거됩니다.개인 정보 보호 및 보안을 위해 이러한 스크립트는 전체 디스크 암호화가 있는 컴퓨터에서만 실행해야 합니다.보안 전문가가 메모리에 키를 보호하는 소프트웨어를 작성하는 것이 가능하지만, 이러한 Python 스크립트는 암호화 키와 암호를 문자열에 저장하여 Python에서 가비지 수집합니다.즉, 비밀 키와 암호는 한동안 RAM에 저장되어 있으며, 여기서 스왑 파일과 디스크로 유출되어 공격자가 복구할 수 있습니다.이렇게 하면 암호화된 백업을 사용할 수 없게 됩니다.
백업 암호 해독 방법: 이론적으로
iOS 보안 백서는 파일별 키, 보호 클래스, 보호 클래스 키 및 키백에 대한 기본 개념을 저보다 더 잘 설명합니다.이러한 내용에 익숙하지 않은 경우 몇 분 동안 관련 부분을 읽어 보십시오.
이제 iOS의 모든 파일이 자체 파일당 랜덤 암호화 키로 암호화되고, 보호 클래스에 속하며, 파일당 암호화 키는 보호 클래스 키로 감싸인 파일 시스템 메타데이터에 저장됩니다.
암호 해독 방법:
에저된키디합니다코에 .
BackupKeyBag
의Manifest.plist
이 구조에 대한 대략적인 개요는 백서에 나와 있습니다.iPhone Wiki는 이진 형식을 설명합니다. 4바이트 문자열 유형 필드, 4바이트 빅 엔디안 길이 필드, 그 다음 값 자체입니다.입니다.
ITER
방송국과 방송국SALT
소금DPSL
횟수 및 복 횟 수DPIC
다음과 같이 수행합니다.CLS
,WPKY
키 은열 쇠감열백업 암호를 사용하여 올바른 PBKDF2 소금과 반복 횟수를 사용하여 32바이트 키를 얻습니다.를 SHA256과 사용합니다.
DPSL
그리고.DPIC
라운드와 SHA1 라운드.ITER
그리고.SALT
.RFC 3394에 따라 포장된 각 키를 풉니다.
를 해독하려면 보호 를 " " " "에서 하십시오.
ManifestKey
Manifest.plist
그리고 그것을 벗깁니다.이제 모든 파일 메타데이터가 포함된 SQLite 데이터베이스가 있습니다.있는 암호화 키 및 합니다.
Files.file
포는이함플데가 포함된 이진 열EncryptionKey
그리고.ProtectionClass
출바작초길제태거그이트기에서 초기 합니다.EncryptionKey
하기 전에.그런 다음 백업 암호로 풀었던 클래스 키로 풀어서 최종 암호 해독 키를 추출합니다.그런 다음 CBC 모드에서 0 IV로 AES를 사용하여 파일의 암호를 해독합니다.
백업 암호 해독 방법: 실제로
먼저 라이브러리 종속성이 필요합니다.홈브루가 설치된 Python 2.7 또는 3.7을 사용하여 Mac에 있는 경우 다음을 사용하여 종속성을 설치할 수 있습니다.
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}
추가신용장
Bedrune과 Sigwald가 게시한 아이폰 데이터 보호 코드는 저장된 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 포트가 있습니다.
미안하지만, pbkdf2나 심지어 그것의 변형을 포함하여 더 복잡할 수도 있습니다.WWDC 2010 세션 #209를 들어보십시오. 주로 iOS 4의 보안 조치에 대해 설명하지만 백업의 별도 암호화와 관련성에 대해서도 간략하게 설명합니다.
비밀번호를 모르면 절대 해독할 수 없습니다. 심지어 폭력적인 방법으로도 말이죠.
암호를 알고 있는 사용자가 백업 데이터에 액세스할 수 있도록 한다고 가정해 보겠습니다.
어떤 알고리즘이 사용되는지 파악하기 위해 아이튠즈의 실제 코드를 살펴볼 방법이 없을 것 같습니다.
뉴턴 시절에는 프로그램에서 데이터를 해독해야 했고 알고리즘을 이해할 필요 없이 암호 해독 기능을 직접 호출할 수 있었습니다.불행하게도 더 이상 그렇게 쉽지 않습니다.
저는 아이튠즈 코드를 역설계할 수 있는 숙련된 사람들이 주변에 있을 것이라고 확신합니다. 당신은 단지 그들에게 관심을 갖기만 하면 됩니다.
이론적으로, Apple의 알고리즘은 정확한 암호화 방법을 알고 있는 공격자에게 데이터를 여전히 안전하게(즉, 무차별 대입 방식으로 사실상 깨지지 않음) 하는 방식으로 설계되어야 합니다.그리고 WWDC 세션 209에서 그들은 이것을 달성하기 위해 무엇을 하는지에 대한 세부사항들을 꽤 깊게 살펴보았습니다.당신의 좋은 의도를 애플 보안팀에 알려주면 실제로 답변을 받을 수 있을 것입니다.결국, 그들조차도 난독화에 의한 보안이 실제로 효율적이지 않다는 것을 알아야 합니다.보안 메일 목록을 사용해 보십시오.그들이 응답하지 않더라도, 아마도 리스트에 있는 다른 누군가가 조용히 도움으로 응답할 것입니다.
행운을 빕니다.
시도해 본 적은 없지만, Elcomsoft는 법의학적 목적으로 백업을 해독할 수 있다고 주장하는 제품을 출시했습니다.솔루션을 직접 엔지니어링하는 것만큼 멋지지는 않겠지만, 더 빠를 수도 있습니다.
http://www.elcomsoft.com/eppb.html
당신은 Erica Sadun의 mdhelper 명령줄 유틸리티(OS X 바이너리 & 소스)의 복사본을 가져와야 합니다.주소록 및 SMS 데이터베이스, 기타 애플리케이션 메타데이터 및 설정을 포함하여 iPhone/iPod Touch 백업의 내용을 나열하고 추출할 수 있습니다.
언급URL : https://stackoverflow.com/questions/1498342/how-to-decrypt-an-encrypted-apple-itunes-iphone-backup
'programing' 카테고리의 다른 글
파일/폴더의 수정 날짜 찾기 (0) | 2023.07.28 |
---|---|
스프링 부트 - 인터셉터에서 컨트롤러의 메서드로 인수 전달 (0) | 2023.07.28 |
PowerShell V2의 Send-Mail Message를 사용하여 Gmail로 메일 보내기 (0) | 2023.07.28 |
종료 시 SQL*Plus가 커밋되는 이유는 무엇입니까? (0) | 2023.07.28 |
자바스크립트 이벤트 수신기를 제거하려면 어떻게 해야 합니까? (0) | 2023.07.28 |