Skip to content

Instantly share code, notes, and snippets.

@ceramicwhite
Forked from geekman/parse_keybag.py
Last active June 11, 2024 19:16
Show Gist options
  • Select an option

  • Save ceramicwhite/11da2e0b2b8b11341eb67d19d7a84ace to your computer and use it in GitHub Desktop.

Select an option

Save ceramicwhite/11da2e0b2b8b11341eb67d19d7a84ace to your computer and use it in GitHub Desktop.
extract & parse the BackupKeyBag from an iTunes Backup
#!/usr/bin/env python
#
# extracts and parse BackupKeyBag
#
# 2017.02.04 darell tan
#
# Update 2024.06.11 Jasper
import plistlib
import struct
import sys
from binascii import hexlify
from collections import OrderedDict
from io import BytesIO
def getKeybagFile(manifest_file):
"""
Retrieves the BackupKeyBag embedded within the Manifest.plist.
"""
with open(manifest_file, 'rb') as f:
data = f.read()
if data.startswith(b'bplist'):
pl = plistlib.loads(data)
else:
pl = plistlib.loads(data)
assert 'Version' in pl
return BytesIO(pl['BackupKeyBag'])
class Keybag:
def __init__(self, f):
self.hdr = OrderedDict()
self.keys = []
self.f = f if hasattr(f, 'read') else open(f, 'rb')
self._parse()
def _parse(self):
keys = []
currKey = OrderedDict()
while True:
hdr = self.f.read(8)
if hdr == b'':
break
typ, sz = struct.unpack('>4sI', hdr)
data = self.f.read(sz)
if sz == 4:
data, = struct.unpack('>I', data)
# UUID usually first item of each entry
if typ == b'UUID':
if 'UUID' in currKey:
keys.append(currKey)
else:
self.hdr = currKey
currKey = OrderedDict()
currKey[typ.decode('utf-8')] = data
if currKey:
keys.append(currKey)
self.keys = keys
def dump(self):
for k, v in self.hdr.items():
print(k, v)
print('-' * 10)
def decode(typ, val):
if typ == 'UUID':
v = hexlify(val).decode('utf-8')
return '%s...%s' % (v[:6], v[-4:])
elif not isinstance(val, int):
return hexlify(val).decode('utf-8')
else:
return repr(val)
for key in self.keys:
print(', '.join('%s: %s' % (k, decode(k, v)) for k, v in key.items()))
def __repr__(self):
return repr(self.keys)
def main():
stream = getKeybagFile(sys.argv[1])
k = Keybag(stream)
k.dump()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment