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 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 unlockandfastboot flashing unlock_criticalcommands (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.
| 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 |
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 USBThe --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).
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 |
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.binThe 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.
The preloader and DA are loaded and run in sequence by mtkclient:
- mtkclient sends the patched preloader to SRAM via the brom handshake. The preloader boots on the device and answers the USB protocol.
- mtkclient uploads the patched DA to DRAM through the running preloader. The DA takes over the USB protocol and serves the read/write commands.
- The user runs
mtk r/wcommands 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.