hacks/dump-imessages/iphone-dataprotection/python_scripts/nand/partition_tables.py

133 lines
4.6 KiB
Python

from construct import *
from zipfile import crc32
GPT_HFS = "005346480000aa11aa1100306543ecac".decode("hex")
GPT_EMF = "00464d450000aa11aa1100306543ecac".decode("hex")
LWVM_partitionRecord = Struct("LWVM_partitionRecord",
String("type", 16),
String("guid", 16),
ULInt64("begin"),
ULInt64("end"),
ULInt64("attribute"),
String("name", 0x48, encoding="utf-16-le", padchar="\x00")
)
LWVM_MAGIC = "6a9088cf8afd630ae351e24887e0b98b".decode("hex")
LWVM_header = Struct("LWVM_header",
String("type",16),
String("guid", 16),
ULInt64("mediaSize"),
ULInt32("numPartitions"),
ULInt32("crc32"),
Padding(464),
Array(12, LWVM_partitionRecord),
Array(1024, ULInt16("chunks"))
)
GPT_header = Struct("GPT_header",
String("signature", 8),
ULInt32("revision"),
ULInt32("header_size"),
SLInt32("crc"), #hax to match python signed crc
ULInt32("zero"),
ULInt64("current_lba"),
ULInt64("backup_lba"),
ULInt64("first_usable_lba"),
ULInt64("last_usable_lba"),
String("disk_guid", 16),
ULInt64("partition_entries_lba"),
ULInt32("num_partition_entries"),
ULInt32("size_partition_entry"),
ULInt32("crc_partition_entries")
)
GPT_entry = Struct("GPT_entry",
String("partition_type_guid", 16),
String("partition_guid", 16),
ULInt64("first_lba"),
ULInt64("last_lba"),
ULInt64("attributes"),
String("name", 72, encoding="utf-16-le", padchar="\x00"),
)
GPT_partitions = RepeatUntil(lambda obj, ctx: obj["partition_type_guid"] == "\x00"*16, GPT_entry)
APPLE_ENCRYPTED = 0xAE
MBR_entry = Struct("MBR_entry",
Byte("status"),
Bytes("chs_start",3),
Byte("type"),
Bytes("chs_last",3),
ULInt32("lba_start"),
ULInt32("num_sectors")
)
MBR = Struct("MBR",
String("code",440),
ULInt32("signature"),
ULInt16("zero"),
Array(4, MBR_entry),
OneOf(ULInt16("magic"), [0xAA55])
)
def parse_mbr(data):
try:
mbr = MBR.parse(data)
if mbr.MBR_entry[0].type == 0xEE:
print "Found protective MBR"
return None
res = mbr.MBR_entry[:2]
for p in res:
p.first_lba = p.lba_start
p.last_lba = p.lba_start + p.num_sectors
return res
except:
return None
def parse_gpt(data):
gpt = GPT_header.parse(data)
if gpt.signature != "EFI PART":
return None
print "Found GPT header current_lba=%d partition_entries_lba=%d" % (gpt.current_lba, gpt.partition_entries_lba)
assert gpt.partition_entries_lba > gpt.current_lba
check = gpt.crc
gpt.crc = 0
actual = crc32(GPT_header.build(gpt))
if actual != check:
print "GPT crc check fail %d vs %d" % (actual, check)
return None
return gpt
def parse_lwvm(data, pageSize):
try:
hdr = LWVM_header.parse(data)
if hdr.type != LWVM_MAGIC:
print "LwVM magic mismatch"
return
tocheck = data[:44] + "\x00\x00\x00\x00" + data[48:0x1000]
check = crc32(tocheck) & 0xffffffff
if check != hdr.crc32:
return None
print "LwVM header CRC OK"
partitions = hdr.LWVM_partitionRecord[:hdr.numPartitions]
deviceSize=0
#XXX: HAAAAAAAX
for s in [8, 16, 32, 64, 128]:
if hdr.mediaSize < (s* 1024*1024*1024):
deviceSize = s
break
for i in xrange(len(hdr.chunks)):
if hdr.chunks[i] == 0x0:
lba0 = (i * deviceSize*1024*1024) / pageSize
partitions[0].first_lba = lba0
partitions[0].last_lba = lba0 + (partitions[0].end - partitions[0].begin) / pageSize
elif hdr.chunks[i] == 0x1000:
lbad = (i * deviceSize*1024*1024) / pageSize
partitions[1].first_lba = lbad
partitions[1].last_lba = lbad + (partitions[1].end - partitions[1].begin) / pageSize
return partitions
except:
return None