Skip to content

Repository files navigation

BraX3 repair tools

This repository contains the exact byte-level patches needed to make mtkclient able to read and write partitions on a BraX3 phone bricked by SP Flash Tool's "Format All + Download" when the operation failed with an empty error message partway through flashing.

The brick

The BraX3 phone (an MTK Dimensity 6100+ device, SoC MT6835V/ZA, hwcode 0x1209) was bricked as follows (cf this issue and this community thread):

  • The phone was connected to the wifi and the June 2026 update of iodéOS (OTA update) was installed.
  • These instructions were followed to unlock the bootloader. However after the fastboot flashing unlock and fastboot flashing unlock_critical commands (confirmed with Volume Up) were executed and the phone restarted, the phone entered a boot loop.
  • SP Flash tool was used with “Format All + Download” (as “Download only” would not work) with iode-7.3-20260305-brax3-spflash. This process failed with an empty error message.
  • Then SP Flash tool was not able to communicate with the phone anymore with the same empty error message.

This repository's patches allow to use mtkclient to communicate with such a bricked phone, allowing to read and write partitions.

What is in this repository

File What it is
patch_preloader.py Python script that produces preloader_k6835v1_64_patched.bin from the stock preloader.
patch_da.py Python script that produces DA_BR_patched.bin from the stock download agent.
preloader_k6835v1_64_patched.bin Patched preloader — drops the watchdog-reset and crypto-auth gates that prevent mtkclient from talking to the running preloader.
DA_BR_patched.bin Patched download agent — drops the per-partition Security deny, Signature(Entity) invalid., and img_auth_required SBC verification gates that block mtk w <partition>.
PATCHES.md The technical reference: every patch site, its exact byte values, what the original instruction does, and why it needs to change.

Exact SHA-256 sums of the prebuilt patched binaries in this repository:

File Size SHA-256
preloader_k6835v1_64_patched.bin 386,004 bytes a6068ad61f3c778531dc8dbe64f99298940c248ac5f459fd186d0adadfad3481
DA_BR_patched.bin 849,768 bytes 21ab67dc6759b2726f11c2d734ba76f80a9077330bf48eea6b99726ed4bd6ffe

How to use the prebuilt patched binaries

The two patched binaries are the only files mtkclient needs to operate on the bricked device. Point mtkclient at them via --preloader and --loader:

# Read any partition (e.g. back up the current para partition)
mtk r para para.bin \
    --preloader preloader_k6835v1_64_patched.bin \
    --loader    DA_BR_patched.bin \
    --plstage --stock --debugmode --uartloglevel 0 --logchannel USB

# Write any partition (e.g. restore para from a backup)
mtk w para para.bin \
    --preloader preloader_k6835v1_64_patched.bin \
    --loader    DA_BR_patched.bin \
    --plstage --stock --debugmode --uartloglevel 0 --logchannel USB

The --plstage flag is not available in upstream mtkclient yet, cf this PR on mtkclient, in the mean time, use the plstage branch of this fork of mtkclient. It tells mtkclient to upload the patched preloader via the brom handshake and run it, then send the patched DA to the running preloader.

The --stock flag bypasses mtkclient's built-in DA patches so that the DA is used as-is.

The --debugmode --uartloglevel 0 --logchannel USB flags add extra logging (optional).

Source of the stock binaries

The stock DA_BR.bin and preloader_k6835v1_64.bin that this repository patches come from the LunarOS firmware shared in this post of the Brax community forum.

Exact SHA-256 sums of the stock binaries:

File Size SHA-256
preloader_k6835v1_64.bin 386,004 bytes 64b218d2ea054af02017abffff52310806702d827e7b775376ea7e15ce655434
DA_BR.bin 849,768 bytes 97e22d89126a1aabedb2773b8f4ac50ea0dcb58c6e8c4cb95abe5a0b95ea0fe3

How to reproduce the patches from source

If you want to verify the binaries or apply the patches to a different revision of the BraX3 binaries yourself:

# Preloader: stock 386,004 bytes -> patched 386,004 bytes
python3 patch_preloader.py \
    --input  /path/to/preloader_k6835v1_64.bin \
    --output preloader_k6835v1_64_patched.bin

# Download agent: stock 849,768 bytes -> patched 849,768 bytes
python3 patch_da.py \
    --input  /path/to/DA_BR.bin \
    --output DA_BR_patched.bin

The scripts reject inputs that do not match the expected revision (they verify magic strings, file size, hash slots, and every patch site byte-for-byte before writing). Run them with --dry-run to see what would change without writing anything.

How the two patches interact

The preloader and DA are loaded and run in sequence by mtkclient:

  1. mtkclient sends the patched preloader to SRAM via the brom handshake. The preloader boots on the device and answers the USB protocol.
  2. mtkclient uploads the patched DA to DRAM through the running preloader. The DA takes over the USB protocol and serves the read/write commands.
  3. The user runs mtk r/w commands against the running DA.

For step 1 to work, the patched preloader must (a) not watchdog-reset during its DRAM-init phase and (b) not refuse USB reads on the grounds of crypto-init failure. The crypto-init bypass is required so that mtk peek works (the preloader USB read32 handler returned 0x1000 CRYPTO_INIT_FAIL on every peek without it).

For step 2 to work, the preloader must accept the modified DA. The DA contains a SHA-256 hash of its own DA2 region in a 48-byte slot at the end of DA1, and the preloader (usbdl_verify_da at file 0x45984) recomputes that hash and compares against the slot before jumping to DA2. The DA patch script recomputes the hash after applying the byte-level modifications, so the preloader still accepts the image.

For step 3 to work, the DA must not refuse writes on the grounds of per-partition security policy. That is what the DA patches do.

About

Tools (patched preloader and download agent) to repair a bricked BraX3 phone with mtkclient

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages