From 7bfac8dc1bd69f23d2bf564e604e181292d52263 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 7 Jul 2019 23:53:15 +0200 Subject: Updated the code for the unpackbootimg tool. --- python/unpackbootimg.py | 184 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 134 insertions(+), 50 deletions(-) diff --git a/python/unpackbootimg.py b/python/unpackbootimg.py index addc408..d21e469 100644 --- a/python/unpackbootimg.py +++ b/python/unpackbootimg.py @@ -1,11 +1,116 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- import argparse -import sys import pychrysalide from pychrysalide.analysis.contents import FileContent -from pychrysalide.format.bootimg import BootimgFormat +from pychrysalide.format.bootimg import BootImgFormat +import struct + + +def _value_to_string(val): + """Convert a field into a string.""" + + encodings = [ 'ascii', 'utf-8', 'utf-16' ] + + desc = None + + for enc in encodings: + + try: + desc = '"%s"' % val.decode(enc) + except: + desc = None + + if desc: + break + + if not(desc): + + count = val.find(b'\x00') + + if count == -1: + count = len(val) + + desc = '%u byte(s)' % count + + return desc + + +def _value_to_size(val): + """Convert a field into a human-readable size.""" + + unit = 0 + + units = [ '', 'Kb', 'Mb', 'Gb' ] + + for i in range(3): + if val > 1024: + val /= 1024 + unit += 1 + + if val == int(val): + return '%u%s' % (val, units[unit]) + else: + return '%.1f%s' % (val, units[unit]) + + +def _value_to_id(val): + """Convert a field into an identifier.""" + + values = struct.unpack(' length: + length = len(key) + 1 + + line = ' {:<%u} {:}' % length + + title = ' Boot image header' + + print() + print(title) + print('=' * len(title)) + + for key, val in items: + print(line.format(key + ':', val)) + + print() if __name__ == '__main__': @@ -13,67 +118,46 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument('bootimg', help='path to the Android boot imgage to process') + parser.add_argument('-i', '--info', help='display information about the boot image', action='store_true') + parser.add_argument('-k', '--kernel', help='dump the kernel embedded in the boot image', action='store_true') + parser.add_argument('-r', '--ramdisk', help='dump the ramdisk embedded in the boot image', action='store_true') + parser.add_argument('filename', help='path to the Android boot image', metavar='boot.img') args = parser.parse_args() - cnt = FileContent(args.bootimg) + cnt = FileContent(args.filename) if cnt is None: sys.exit('No content to load!') - fmt = BootimgFormat(cnt) - - if fmt is None: - sys.exit('Failed to load the boot image!') - - oattribs = [ - 'magic', - 'kernel_size', - 'kernel_addr', - 'ramdisk_size', - 'ramdisk_addr', - 'second_size', - 'second_addr', - 'tags_addr', - 'page_size', - 'header_version', - 'os_version', - 'name', - 'cmdline', - 'extra_cmdline' - ] + fmt = BootImgFormat(cnt) + + status = fmt.analyze() + + if not(status): + sys.exit('Bad boot image!') - maxlen = 0 + if args.info: + show_info(fmt) - for a in oattribs: - if len(a) > maxlen: - maxlen = len(a) + if args.kernel: - name = ' {0:<%u}' % (maxlen + 1) + if fmt.kernel: - header = fmt.get_header() + with open('kernel.bin', 'wb') as fd: + fd.write(fmt.kernel.data) - for a in oattribs: + else: - v = getattr(header, a) + print('No kernel to extract!') - value = '0x%x' % v if type(v) == int else v + if args.ramdisk: - print(name.format(a + ':'), value) + if fmt.ramdisk: - with open(args.bootimg + '-' + a, 'w') as out: - out.write(value) - out.write('\n') + with open('ramdisk.bin', 'wb') as fd: + fd.write(fmt.ramdisk.data) - contents = { - 'kernel': fmt.get_kernel(), - 'ramdisk': fmt.get_ramdisk(), - 'second_stage': fmt.get_second_stage(), - 'recovery_dtbo': fmt.get_recovery_dtbo() - } + else: - for k, v in contents.items(): - if v: - with open(args.bootimg + '-' + k, 'wb') as out: - out.write(v.data) + print('No ramdisk to extract!') -- cgit v0.11.2-87-g4458