Skip to content

Instantly share code, notes, and snippets.

@1328
Forked from geekman/parse_keybag.py
Last active February 5, 2020 13:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save 1328/4e02550b801bb2200dcca65dd4b0c396 to your computer and use it in GitHub Desktop.
Save 1328/4e02550b801bb2200dcca65dd4b0c396 to your computer and use it in GitHub Desktop.
extract & parse the BackupKeyBag from an iTunes Backup
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