summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-07-07 21:53:15 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-07-07 21:53:15 (GMT)
commit7bfac8dc1bd69f23d2bf564e604e181292d52263 (patch)
tree1c364b8e5babfaee95e249aa886bf26d9fffeff7
parent7340856bf8e35b7a9c43b3e3267125b0821e359f (diff)
Updated the code for the unpackbootimg tool.
-rw-r--r--python/unpackbootimg.py184
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!')