-
-
Save 1328/4e02550b801bb2200dcca65dd4b0c396 to your computer and use it in GitHub Desktop.
extract & parse the BackupKeyBag from an iTunes Backup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
# updated to work with py3 using only standard lib modules | |
# unsure if it will work with py2 still... | |
import plistlib | |
import struct | |
import sys | |
from binascii import hexlify | |
from collections import OrderedDict | |
from functools import partial | |
def get_manifest_plist(manifest_file): | |
""" | |
Retrieves the BackupKeyBag embedded within the Manifest.plist. | |
""" | |
with open(manifest_file, 'rb') as f: | |
#data = f.read() | |
#pl = Structure.from_bin(data) if data.startswith('bplist') else Structure.from_xml(data) | |
pl = plistlib.load(f) | |
assert 'Version' in pl | |
return pl | |
def take(it, size): | |
'''consume and return size data from it''' | |
return bytearray(next(it) for _ in range(size)) | |
def parse_blob(data): | |
'''process a data bytes object, yields key, value | |
expects a data structure of | |
4 bytes key | |
4 bytes size | |
X bytes value | |
''' | |
it = iter(data) | |
eat = partial(take, it) | |
while True: | |
data = eat(8) | |
if len(data) == 0: | |
break | |
key, sz = struct.unpack('>4sI', data) | |
key = key.decode() | |
value = eat(sz) | |
if sz == 4: | |
value, *_ = struct.unpack('>I', value) | |
else: | |
value = hexlify(value).decode() | |
yield key, value | |
def parse_BackupKeyBag(data): | |
'''parse out different uuids from keybag plist blob''' | |
found = OrderedDict() | |
for key, value in parse_blob(data): | |
if key == 'UUID': | |
if found: | |
yield found | |
found = OrderedDict() | |
if key in found: | |
raise Exception('Duplicate key found!') | |
found[key] = value | |
yield found # drop last one | |
def main(): | |
plist = get_manifest_plist(sys.argv[1]) | |
keybag = parse_BackupKeyBag(plist['BackupKeyBag']) | |
header = next(keybag) | |
print('Version: {VERS}\t Type: {TYPE}'.format(**header)) | |
for entry in keybag: | |
for key,value in entry.items(): | |
print('{}: {}'.format(key, value)) | |
print('-'*20) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment