# Android_boot_image_editor: Unpack and Repack Android Boot Images

> Android_boot_image_editor is a Gradle driven Java tool that unpacks and repacks boot.img, vendor_boot.img, vbmeta.img, dtbo.img, sparse images and OTA payload.bin files so their contents can be inspected and modified. It requires JDK 17 and Python 3, and it only handles images that follow the AOSP verified boot flow.

**cfig/Android_boot_image_editor** — Parsing and re-packing Android boot.img/vbmeta.img/payload.bin, supporting Android 16

- Repository: https://github.com/cfig/Android_boot_image_editor
- Stars: 1,335 · Forks: 301
- Language: Java
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/cfig-android-boot-image-editor

## Two Gradle Tasks: unpack and pack

The workflow is deliberately small. You put a boot image in the working directory, run the unpack task, edit whatever you find, and run the pack task to get a new image back. The README gives the whole loop in three commands:

```bash
cp <original_boot_image> boot.img
./gradlew unpack
```

and then, after editing the extracted contents:

```bash
./gradlew pack
```

The result lands in the current directory as boot.img.signed. The name matters, because the signed suffix tells you the tool has produced a container with a signature over it, and it is a different filename from the input, which means the original image is never overwritten by accident.

The project is written in Java, with a Gradle build in Kotlin DSL, and it pulls in a number of native tools at run time rather than reimplementing them. The repository tree shows where the pieces come from, with aosp/ holding AOSP derived code, avbImpl/ for the Android Verified Boot pieces, bbootimg/ for the boot image handling, helper/ and tools/ for the wrappers, lazybox/ for supporting pieces, and integrationTest.py for the end to end checks.

## The Work Directory: kernel, root, dtb and Two JSON Sidecars

After unpacking, the contents land under build/unzip_boot in a flat, readable form, and the README shows the shape of it:

```text
build/unzip_boot/
├── boot.json     (boot image info)
├── boot.avb.json (AVB only)
├── kernel
├── second        (2nd bootloader, if exists)
├── dtb           (dtb, if exists)
├── dtbo          (dtbo, if exists)
└── root          (extracted initramfs)
```

The two JSON files are the metadata the tool keeps about the image it parsed. boot.json records the boot image info, and boot.avb.json appears only for AVB images, which means the presence of that second file is itself a quick way to tell which verified boot version you are dealing with.

The extracted items are conditional, and the parentheses say so. The second stage bootloader is present only if the image has one, and the device tree blobs appear only if the image carries them. root is the extracted initramfs, which is where the bulk of a modified system usually lives, and the kernel is the one file that is almost always there. Because everything is flattened into plain files and a directory, editing means using ordinary tools on ordinary files rather than a bespoke format editor.

## Verified Boot Is a Precondition, Not a Feature

The support matrix carries a warning that decides whether the tool applies at all. The boot.img must follow the AOSP verified boot flow, which means either a boot image signature in the VBoot 1.0 format or an AVB hash footer in the VBoot 2.0 format. Images that do not follow that flow are out of scope.

This is a real constraint on the workflows the tool supports. A device that boots with an unlocked bootloader and no verification chain, or an image that has been stripped of its footer, is not going to round trip through the unpack and pack tasks in a way that the device will accept.

The AVB side of the repository is where that verification logic lives, in the avbImpl/ directory, and the fact that the tool regenerates a signed output rather than just a raw image is the practical payoff. A user who changes a file inside the image changes the hash the footer commits to, so the tool has to rebuild the descriptor chain as well, and the JSON sidecar in the work directory is where the result of that negotiation is recorded for inspection.

## The Image Types Covered, and the Ones That Need Linux

The support table lists the containers the tool handles and, importantly, where each one works. The boot family covers boot.img, init_boot.img, boot-debug.img and boot-test-harness.img on all platforms, and the vendor boot family covers vendor_boot.img, vendor_boot-debug.img and vendor_kernel_boot.img, also on all platforms. The recovery family covers recovery.img and recovery-two-step.img, and the vbmeta family covers vbmeta.img and files such as vbmeta_system.img, all of them on all platforms.

The platform column narrows from there. dtbo.img and standalone .dtb files are listed for linux and mac only, and sparse images such as system.img, vendor.img and product.img are listed for linux only. The OTA payload, payload.bin, is listed for all platforms, with a note that on Windows it works through git-bash.

So the practical rule is that everything works on a Linux box, macOS loses the sparse image support, and Windows works for the boot, vbmeta and payload cases but not for the sparse images or the device tree files. If your images are system.img style sparse partitions rather than boot images, you need Linux.

## vbmeta and boot Have to Be Repacked Together

The examples section contains the instruction that causes the most confusion for newcomers. If your vbmeta.img contains the hash of boot.img, you must update the vbmeta image together with it. The sequence looks the same as the basic flow, with both files present in the working directory:

```bash
rm *.img
cp <your_boot_image> boot.img
cp <your_vbmeta_image> vbmeta.img
./gradlew unpack
./gradlew pack
```

The outputs are updated together, boot.img.signed and vbmeta.img.signd, and the README says you can then flash them to your device.

The reason is the chain of trust. The vbmeta image holds a hash descriptor for the boot image, so editing the boot image invalidates that hash, and a device that still has the old vbmeta will refuse the new boot image. Repacking both in a single run is what keeps the chain consistent.

The same logic applies to vendor_boot.img, and the README has a separate example for that case, noting that most devices include a hash descriptor of vendor_boot.img in vbmeta.img, with Pixel 5 named as the example device.

## Platform Prerequisites Depend on Native Tools

The requirements section explains why the tool needs more than a JDK. You need JDK 17 or newer and Python 3, and then a set of native utilities per platform, because compression, device tree compilation and sparse image handling are delegated to real tools rather than reimplemented.

On Linux or WSL the README lists the packages to install:

```bash
sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils
```

On macOS it is a shorter list:

```bash
brew install lz4 xz dtc
```

And on Windows the README asks you to install openssl and a device tree compiler with chocolatey:

```bash
choco install openssl dtc-msys2 zip vim gzip 7zip
```

The Linux line is the fullest, and it includes the sparse and erofs utilities that the sparse image support depends on, plus p7zip for archive handling. If you plan to work with sparse images, the Linux package list is the one that matches the feature set.

## Device Compatibility Is Empirical and Includes Failures

The compatibility table is the most informative part of the README, because it lists failures as well as successes. Pixel 7, Pixel 3, ADT-3, a Redmi K30 4G, a TS10 head unit, a Pixel XL, a Nexus 9, a Nexus 5x, a ZTE Z18 and an OPPO K3 are marked as compatible, in several cases with a link to additional tricks in doc/additional_tricks.md. The OPPO K3 entry is precise about the split, compatible for recovery.img and not for boot.img.

Then there are the ones marked N. A Moto X from 2013, a VIVO X7 and a Realme GT Neo 3, the last with a link to issue 105 in the tracker. There is also a note that the K3 entry and the Nexus 9 entry need tricks, and the Nexus 9 row is annotated as compatible with some tricks.

The pattern is clear. Success on a given model is tied to a specific image and a specific Android build, verified by the people who tried it, so a device appearing in the table for one build tells you little about the next one. Additional per-device notes live in doc/additional_tricks.md, and the repository carries a CODE_OF_CONDUCT.md alongside the Apache-2.0 LICENSE.md.

## Conclusion

Android_boot_image_editor fits a developer who needs to look inside a boot image, change a kernel or an initramfs, and put the result back into a signed container without hand assembling the header, the ramdisk and the AVB descriptors. It is a poor fit for an image that does not follow the AOSP verified boot flow, since the tool requires either a VBoot 1.0 boot image signature or a VBoot 2.0 AVB hash footer, and for a device outside the compatibility table, where the README records several models as not working. Before starting, install the toolchain listed for your platform, and remember that if your vbmeta image contains a hash of boot.img you must unpack and pack both together. The licence is Apache-2.0, the newest release tag is v15_r1 from 2024-09-15, and the last push was on 2026-08-06.

## FAQ

### How do I unpack and repack an Android boot image with Android_boot_image_editor?

Copy the image into the working directory as boot.img, run ./gradlew unpack, edit the extracted contents under build/unzip_boot, then run ./gradlew pack. The repacked image is written to the current directory as boot.img.signed.

### What do I need installed before using Android_boot_image_editor?

JDK 17 or newer and Python 3, plus native tools per platform: on Linux or WSL the apt list including device-tree-compiler, lz4, xz-utils and the sparse and erofs utilities, on macOS `brew install lz4 xz dtc`, and on Windows openssl and a device tree compiler installed through chocolatey.

### Why do I need to repack vbmeta.img together with boot.img?

Because if your vbmeta.img contains the hash of boot.img, editing the boot image invalidates that hash. The README says you must update the vbmeta image together with it, and that both boot.img.signed and vbmeta.img.signd are then produced in the same run so you can flash them to the device.

### Does Android_boot_image_editor work on Windows?

Partly. The support table lists boot, vendor boot, recovery, vbmeta and the OTA payload.bin for all platforms, with payload.bin noted as working through git-bash on Windows, while dtbo.img, standalone .dtb files and sparse images are limited to Linux and macOS, with sparse images listed for Linux only.

### What is the difference between boot.json and boot.avb.json?

Both appear in the build/unzip_boot directory after an unpack. boot.json holds the boot image info, and boot.avb.json is present only for AVB images, so its presence tells you the image uses the VBoot 2.0 AVB hash footer rather than a VBoot 1.0 boot image signature.

## Sources

- [cfig/Android_boot_image_editor on GitHub](https://github.com/cfig/Android_boot_image_editor)
- [Issues](https://github.com/cfig/Android_boot_image_editor/issues)
- [License: Apache-2.0](https://github.com/cfig/Android_boot_image_editor/blob/master/LICENSE)
- [README](https://github.com/cfig/Android_boot_image_editor/blob/master/README.md)
- [Releases](https://github.com/cfig/Android_boot_image_editor/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cfig-android-boot-image-editor
