imjtool (formerly known as imgtool)

The imjtool utility is another one of the tools I'm including in my book, this time to accompany the chapter about the Boot process. I deal a lot with the internal format of images there, and realized I needed a quick extractor. This became more important when I started to deal with the L preview, and Google Glass system images I used for research. Over time, as I've encountered more and more proprietary image formats, I've had to extend the tool to support them all. I've also had to change the name (from imgtool to imjtool, as of March 2020) since it turns out the former was taken up by MAME..

By any name, you can get the tool:

👉right here 👈 (or 👉here for the nightly build (macOS only) 👈)

Just unpack the tar. There are macOS (Intel), Linux x86_64 and Android ARM64 images (remember they might need chmod +x to run, and prefix with ./). As usual, you might want to check out the RSS feed, or follow my company's Twitter for more updates.

Darwin users: remember to xattr -d com.apple.quarantine /path/to/imjtool to get past annoying GateKeeper

Why should I care?

Well, most users wouldn't. But if you need a quick tool to unpack Android images, this is useful. Think of it as the inverse of mkbootimg (from the AOSP), coupled with simg2img (the sparse image extractor). Another bonus feature it provides is unpacking the Linux bzimage kernels.

Also, if you're a Darwin user, there's no good LZ4 or XZ built-in to the system.

And if you're ever encountered a broken ZIP file and unzip wasn't too helpful...

Lastly - If you're downloading a rooting tool - and you want to avoid getting malware. I just downloaded An NVIDIA Shield root image, for example - which is really nothing more than a bootimg. So it was trivial to run this tool to extract it - specifically, get to the ramdisk, then cpio -ivd and make sure I can have a peek at it before installing.

What if it doesn't work on _________ (some image or file)?

LET ME KNOW. There are myriad image formats and corner cases which I don't normally run into, but you likely will. If I know about them (preferably through a download link to the image) I can easily fix it.

So how do I use it?

Like So:

morpheus@Zephyr (~)$ imjtool
Usage: imjtool _img_name_ [extract]
Where: _img_name_ is the name of an Android boot or bootloader image (or boot partition)
       [extract]  is an optional parameter to extract the image components

To obtain an Android system image, you can either get it from a zip (e.g. Google's update, Amazon's update.bin, etc), or by dd'ing for a device, then copying it over. Note that some devices (e.g. the HTC One M8) may need a bit of processing, in this case stripping the 256 header HBoot uses:

morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % adb shell                                     

shell@htc_m8wl:/ $ su
root@htc_m8wl:/ # ls -l /dev/block/platform/msm_sdcc.1/by-name/boot            
lrwxrwxrwx root     root              2014-09-26 04:48 boot -> /dev/block/mmcblk0p43
root@htc_m8wl:/ # dd if=/dev/block/mmcblk0p43 of=/data/local/tmp/boot.img
32768+0 records in
32768+0 records out
16777216 bytes transferred in 0.971 secs (17278286 bytes/sec)
root@htc_m8wl:/ # ^D
shell@htc_m8wl:/ $ ^D

# Back on host 
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % adb pull /data/local/tmp/boot.img   
5781 KB/s (16777216 bytes in 2.834s)
# Locating the ANDROID! magic
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) %  od  -A d -t c  boot.img  | grep "A   N   D"         
0000256    A   N   D   R   O   I   D   !   Х  **   `  \0  \0 200  \0  \0
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % dd if=boot.img of=boot bs=256 skip=1                                             
65535+0 records in
65535+0 records out
16776960 bytes transferred in 0.153107 secs (109576753 bytes/sec)
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % imjtool boot extract
Boot image detected
Part      	Size      	Pages	  Addr
Kernel:   	6333904 	3093 	0x8000
Ramdisk:  	834688  	408  	0x2008000
Secondary:	0       	0    	0xf00000
Tags:       1e00000
Flash Page Size: 2048 bytes
Name:    
CmdLine: console=ttyHSL0,115200,n8 androidboot.hardware=qcom user_debug=31 ehci-hcd.park=3
Extracting contents to directory: extracted
Found GZ Magic at offset 16207
gzip: extracted/kernelimage.gz: decompression OK, trailing garbage ignored
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % ls -l extracted
total 46840
-rw-rw-rw-  1 morpheus  staff   6333904 Oct  1 19:28 kernel
-rw-------  1 morpheus  staff  16809984 Oct  1 19:28 kernelimage
-rw-rw-rw-  1 morpheus  staff    834688 Oct  1 19:28 ramdisk
morpheus@Zephyr (~/Documents/Android/Book/src/ImgTool) % file extracted/*
extracted/ramdisk: gzip compressed data, from Unix
extracted/kernel: Linux kernel ARM boot executable zImage (little-endian)
extracted/kernelimage: data  # unrecognized by file(1), but still uncompressed

If you're using the Google images, it's easier:

morpheus@Zephyr (~) % imjtool Images/hammerhead-lpv81c/bootloader-hammerhead-hhz11k.img extract
Boot loader detected
6 images detected, starting at offset 0x200. Size: 2568028 bytes
Image: 0	Size:  310836 bytes	sbl1
Image: 1	Size:  285848 bytes	tz
Image: 2	Size:  156040 bytes	rpm
Image: 3	Size:  261716 bytes	aboot
Image: 4	Size:   18100 bytes	sdi
Image: 5	Size: 1535488 bytes	imgdata
# And the bootloader components are ready in extracted/

You can also use it to extract the filesystem image (basically, do what simg2img does:

morpheus@Zephyr (~) % /imjtool Images/Glass/system.img extract      
Sparse image v1.0 detected
262144 blocks of 4096 bytes compressed into 1304 chunks (39% compressed)
Extracted image is in extracted/image.img
morpheus@Zephyr (~) % file extracted/image.img                                                 
extracted/image.img: Linux rev 1.0 ext4 filesystem data (extents) (large files)
# Ready to mount -o loop..

Lastly, you can use it for imgdata extraction as well (as the file format there is derived from that of the boot image:

morpheus@Zephyr (~) % imjtool Devices/Nexus5/Partitions/imgdata    
Image Data detected
12 images detected, 1, 0 0
Image: 0	Name:             boot	Dimensions:   183x517   Unknowns:   281   868 Offset:     400 Size:    570c
Image: 1	Name:          charger	Dimensions:   390x250   Unknowns:   415   765 Offset:    5c00 Size:    1374
Image: 2	Name:         unlocked	Dimensions:    95x71    Unknowns:   504  1750 Offset:    7000 Size:     7ac
Image: 3	Name:            start	Dimensions:   216x1080  Unknowns:     0   100 Offset:    7800 Size:    6e14
Image: 4	Name:       bootloader	Dimensions:   216x1080  Unknowns:     0   100 Offset:    e800 Size:    ce50
Image: 5	Name:         recovery	Dimensions:   216x1080  Unknowns:     0   100 Offset:   1b800 Size:    af28
Image: 6	Name:         poweroff	Dimensions:   216x1080  Unknowns:     0   100 Offset:   26800 Size:    7eb4
Image: 7	Name:      fastboot_op	Dimensions:   840x1080  Unknowns:     0   400 Offset:   2e800 Size:   d5998
Image: 8	Name:       oem_unlock	Dimensions:  1300x1080  Unknowns:     0     0 Offset:  104200 Size:   4ec90
Image: 9	Name:       unlock_yes	Dimensions:   450x1080  Unknowns:     0  1300 Offset:  153000 Size:    d7c4
Image: 10	Name:        unlock_no	Dimensions:   450x1080  Unknowns:     0  1300 Offset:  160800 Size:    d7c0
Image: 11	Name:     downloadmode	Dimensions:   140x480   Unknowns:   300   890 Offset:  16e000 Size:    8dd8

ChangeLog

/**
  *
  * Not-so-rudimentary-anymore Android image and partition unpacking tool
  *
  * v0.1 - Support unpacking of BootLoader and Boot images, as well as imgdata
  * v0.2 - Supports offset= (for HTC and other boot.imgs where ANDROID! is wrapped)
  *        Supports cmdline= (to override kernel command line)
  *
  * v0.3 - Integrated mkbootimg functionality, added dt_size and id
  *
  * v0.4 - cmdline, addrs..
  *
  * v0.4.1 - Fix for Edvard Holst on Essential PH1 images.. (who uses Essential nowadays, I wonder?)
  * 
  * v0.5 - Update with LZ4 binaries, fix for extract devicetree even if can't uncompress kernel
  *
  * v0.6 - Samsung images (with DT > 0) - Device Tree now found whereever it may hide
  *
  * v0.7 - system.transfer.list support
  *
  * v0.8 - FBPK (SD845 CrossHatch (Pixel 3 XL) bootloader images) AND Huawei Mate
  *        Also compiles cleanly
  *
  * v0.85 - system.transfer.list support for v4 (MTK 64 bit)
  *
  * v1.0  - EFI. Worthy enough a feature that (after three years) I hit version 1 on it, and - JCOLOR
  *
  * v1.1 - Samsung baseband images ("TOC") - 03/04/2020
  *
  * v1.2 - DTBO, super.img (03/20/2020) and integrated Brötli
  *
  * v1.2.1 - Lots of QCOM EFI GUIDs added. Thanks to anonymous contributor!
  *
  * v1.3 - Can now also pack super.img and boot.img based on existing!
  *
  * v1.4 - uBoot uimage format
  *
  * v1.5 - MTK images!
  *
  * v1.5.1 - Fixes: QCOM FPBK fixed (accidentally removed during refactoring around 1.3.. oops)
  *                 UEFI now unpacks files by UI, if presenr, rather than GUID
  *
  * 1.6 - Peek into images to detect payload format, recognize AVB (vbmeta)
  *
  * 1.7 - boot Img header v2,3 and vendor boot images
  *
  * 1.8 - CrAu
  *
  * 1.9 - LZ4/BZ2 integration, selective extraction (extract ..what.. in commandline for some formats)
  *
  * 1.9.1 - Motorola bootloader images (SnL, thanks to NL), some bugfixes
  *
  * 1.10  - FBPK/FBPTv2 (Pixel 6)
  *
  * 2 - Time for version 2 - ZIP support, including partial/broken zips
  *
  * 2 - (still 2.0, beta) PBZX, AA/YAA, LZFSE (BVX2) - even in IMG4 containers (for IPSW unpacking)
  *                       and RTKIT FTAB
  *
  * Acknowledgements/Notes:
  * -----------------------
  *
  *  platform-innovation-framework-for-uefi-complete-specifications-v0.90-v0.97 from Intel was invaluable
  *  for figuring out EFI
  *
  *  Uses Google's Brotli extraction code (there's a limit to how much I'm willing to re-implement!)
  *  Uses libLZMA and LZ4 (because it's everywhere nowadays)
  *  Uses lzfse from Apple's GitHub
  *
  *
  *
  * This tool is part of the free downloads for the book "Android Internals: A Confectioner's Cookbook"
  * But (as of v1.0) is also quite useful or MacOS T2 firmwares and (as of 2.0) for IPSWs.
  *
  * Author: Jonathan Levin, http://NewAndroidBook.com
  *
  *
  * License: Use freely, BUT give credit where due. This way people learn of the website and books.
  *
  *  If you have suggestions for improvement/new image types/etc - let me know and I'll gladly 
  *	     add them in.
  *
  **/

Version 0.2 Changes

Version 0.3-0.4 Changes

Zephyr:/tmp morpheus$ ~/Documents/Android/src/ImgTool/imjtool
Usage: /Users/morpheus/Documents/Android/src/ImgTool/imjtool _img_name_ [cmdline='args to kernel'] [extract]
Where: _img_name_ is the name of an Android boot or bootloader image (or boot partition)
       [extract]  is an optional parameter to extract the image components
       [offset=...]  offset to find ANDROID! magic (e.g. 256 in HTC boot)
       [cmdline='args to kernel'] is an optional parameter specifying the kernel command line
       [addr=0x.....] is an optional base address to load the kernel into

or:     /Users/morpheus/Documents/Android/src/ImgTool/imjtool make _img_name_ _kernel_ _ramdisk_
        Make _img_name by combining kernel and ramdisk and creating header