From c69ce29d950f3d94af36592a4d6e00667a85a2b1 Mon Sep 17 00:00:00 2001 From: flipphoneguy Date: Fri, 1 May 2026 14:40:20 +0300 Subject: [PATCH] Added script to run directly on device in termux --- README.md | 8 +++-- termux_patch.sh | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) create mode 100755 termux_patch.sh diff --git a/README.md b/README.md index 3d35483..0fb664e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Read and write IMEI(s) in the NVRAM `LD0B_001` file on **DuoQin F21 Pro** (single-SIM), **DuoQin F25** (dual-SIM), and **TIQ M5** (dual-SIM, MT6761) — or in a full `nvdata` partition image — offline, no device needed. -> `live_patch.sh` is an interactive ADB script that patches a live rooted MTK device. On dual-SIM devices it prompts for slot 1 or 2 — see [Live device patching](#live-device-patching). +> `live_patch.sh` is an interactive ADB script that patches a live rooted MTK device. On dual-SIM devices it prompts for slot 1 or 2 — see [Live device patching](#live-device-patching). `termux_patch.sh` does the same thing on-device from Termux, no host PC required — see [On-device patching (Termux)](#on-device-patching-termux). ## Install @@ -12,7 +12,7 @@ cd mtk-imei-switcheroo pip install pycryptodome ``` -That's it. Then run `./live_patch.sh` for the interactive flow, or call `python3 imei_tool.py` directly. Needs Python 3.6+; for live patching you also need `adb` (and `fastboot` if you'd rather flash the partition image). +That's it. Then run `./live_patch.sh` for the interactive flow, or call `python3 imei_tool.py` directly. Needs Python 3.6+; for live patching you also need `adb` (and `fastboot` if you'd rather flash the partition image). To patch from the device itself instead of a host PC, run `./termux_patch.sh` from Termux — it auto-installs `python` and `pycryptodome` on first run if missing. ## How it works @@ -60,6 +60,10 @@ The tool auto-detects whether the input is a standalone `LD0B_001` or a partitio - [`flipphoneguy/f21-imei-switcheroo-app`](https://github.com/flipphoneguy/f21-imei-switcheroo-app) — Java/Android port. Cross-verified bit-for-bit against `imei_tool.py`: same AES key, slot offsets `{0x40, 0x60}`, plaintext layout, and MD5-XOR checksum. +## On-device patching (Termux) + +`termux_patch.sh` is the same flow as `live_patch.sh` but runs entirely on the device from Termux — no host PC, no ADB. It checks for `python` and `pycryptodome` (offers to `pkg install` / `pip install` if missing), reads `LD0B_001` directly via `su -c`, runs `imei_tool.py` to rewrite it, copies it back into place, and offers to reboot. Like `live_patch.sh`, it counts populated slots and prompts `[1/2/n]` on dual-SIM or `[y/N]` on single-SIM. Termux must be granted root (Magisk → Superuser → allow Termux). + ## Credits - AES key derivation algorithm from [bkerler/mtkclient](https://github.com/bkerler/mtkclient). diff --git a/termux_patch.sh b/termux_patch.sh new file mode 100755 index 0000000..ecabec1 --- /dev/null +++ b/termux_patch.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# Termux interactive IMEI changer for rooted MTK devices. + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +TOOL="$SCRIPT_DIR/imei_tool.py" + +IMEI_PATH="/mnt/vendor/nvdata/md/NVRAM/NVD_IMEI/LD0B_001" +WORK="$(pwd)/tmp" +mkdir -p "$WORK" +BACKUP="$WORK/backup_LD0B_001.bin" +PATCHED="$WORK/patched_LD0B_001.bin" + +die() { echo "Error: $1" >&2; exit 1; } + +echo "Checking dependencies..." + +if ! command -v python3 >/dev/null 2>&1; then + read -p "Python not installed. Install now? [y/N] " ans + if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then + pkg update && pkg install python || die "Python install failed" + echo "Installed python" + else + die "Python not installed" + fi +fi + +if ! python3 -c "from Crypto.Cipher import AES" 2>/dev/null \ + && ! python3 -c "from Cryptodome.Cipher import AES" 2>/dev/null; then + read -p "pycryptodome not installed. Install now with pip? [y/N] " ans + if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then + pip install pycryptodome || die "pycryptodome install failed" + echo "Installed pycryptodome" + else + die "pycryptodome not installed" + fi +fi + +echo "All dependencies are installed" + +push_replace() { + su -c "mount -o remount,rw /mnt/vendor/nvdata" /dev/null 2>&1 + su -c "mount -o remount,rw /" /dev/null 2>&1 + su -c "cp $PATCHED $IMEI_PATH" /dev/null | grep -q "uid=0" \ + || die "su -c failed: device must be rooted and root must be granted to termux shell" +echo "Device is rooted, continuing..." + +echo "Reading current IMEIs from device..." +su -c "cat $IMEI_PATH" "$BACKUP" 2>/dev/null \ + || die "Cannot read LD0B_001 from device" + +file_size=$(wc -c < "$BACKUP") +[ "$file_size" -eq 384 ] || die "LD0B_001 is $file_size bytes (expected 384) - read may have corrupted the file" + +echo "" +read_output=$(python3 "$TOOL" read "$BACKUP") || die "Read failed (imei_tool.py error above)" +echo "$read_output" | sed 's/^/ /' +echo "" + +populated=$(echo "$read_output" | grep -cv '(empty)') + +if [ "$populated" -ge 2 ]; then + read -p "Change which IMEI? [1/2/n] " choice + case "$choice" in + 1|2) slot="$choice" ;; + *) echo "No changes made."; exit 0 ;; + esac +else + slot=1 + read -p "Change IMEI? [y/N] " ans + case "$ans" in + y|Y) ;; + *) echo "No changes made."; exit 0 ;; + esac +fi + +read -p " New IMEI $slot (15 digits): " new_imei +echo "$new_imei" | grep -qE '^[0-9]{15}$' || die "IMEI must be exactly 15 digits" +echo " Patching IMEI $slot..." +python3 "$TOOL" write "$BACKUP" "$new_imei" -s "$slot" -o "$PATCHED" \ + || die "Patch failed (imei_tool.py error above)" +push_replace +echo " IMEI $slot updated." + +echo "" +read -p "Reboot device now? [y/N] " ans +if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then + su -c "reboot"