diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2019-07-07 21:53:15 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2019-07-07 21:53:15 (GMT) | 
| commit | 7bfac8dc1bd69f23d2bf564e604e181292d52263 (patch) | |
| tree | 1c364b8e5babfaee95e249aa886bf26d9fffeff7 /python | |
| parent | 7340856bf8e35b7a9c43b3e3267125b0821e359f (diff) | |
Updated the code for the unpackbootimg tool.
Diffstat (limited to 'python')
| -rw-r--r-- | python/unpackbootimg.py | 184 | 
1 files 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('<IIIIIIII', val) + +    return ' '.join(['0x%08x' % v for v in values]) + + +def show_info(fmt): +    """Display all available information about a given Boot image.""" + +    hdr = fmt.header + +    items = [ + +        [ 'magic', _value_to_string(hdr.magic) ], +        [ 'kernel_size', _value_to_size(hdr.kernel_size) ], +        [ 'kernel_addr', hex(hdr.kernel_addr) ], + +        [ 'ramdisk_size', _value_to_size(hdr.ramdisk_size) ], +        [ 'ramdisk_addr', hex(hdr.ramdisk_addr) ], + +        [ 'second_size', _value_to_size(hdr.second_size) ], +        [ 'second_addr', hex(hdr.second_addr) ], + +        [ 'tags_addr', hex(hdr.tags_addr) ], +        [ 'page_size', _value_to_size(hdr.page_size) ], +        [ 'header_version', hdr.header_version ], +        [ 'os_version', hex(hdr.os_version) ], +        [ 'name', _value_to_string(hdr.name) ], +        [ 'cmdline', _value_to_string(hdr.cmdline) ], +        [ 'id', _value_to_id(hdr.id) ], +        [ 'extra_cmdline', _value_to_string(hdr.extra_cmdline) ], + +        [ 'recovery_dtbo_size', _value_to_size(hdr.recovery_dtbo_size) ], +        [ 'recovery_dtbo_offset', hex(hdr.recovery_dtbo_offset) ], +        [ 'header_size', _value_to_size(hdr.header_size) ], + +    ] + +    length = 0 + +    for key, _ in items: +        if (len(key) + 1) > 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!') | 
