Skip to content

Instantly share code, notes, and snippets.

@CypherpunkSamurai
Last active November 22, 2025 10:36
Show Gist options
  • Select an option

  • Save CypherpunkSamurai/8976137c2e70c8e1db557718ef72b89b to your computer and use it in GitHub Desktop.

Select an option

Save CypherpunkSamurai/8976137c2e70c8e1db557718ef72b89b to your computer and use it in GitHub Desktop.
ZTE F50 nr_modem_a.bin patcher
#!/usr/bin/env python3
import argparse
import sys
try:
from colorama import Fore, Back, Style, init
except:
print("colorama module not found! install colorama module!")
print("type: pip3 install colorama")
sys.exit(1)
# Initialize colorama to auto-reset styles after each print
init(autoreset=True)
# --- Configuration ---
# The sequence of bytes to find in the file
SEARCH_BYTES = bytes([0x05, 0x24, 0x0B, 0xE0, 0x30, 0x68, 0x03])
# The byte to replace the first byte of the sequence with
PATCH_BYTE = 0x01
# The resulting sequence after the patch (for display purposes)
PATCHED_BYTES = bytes([PATCH_BYTE, 0x24, 0x0B, 0xE0, 0x30, 0x68, 0x03])
def print_hex_view(data, start_address, highlight_offset, highlight_len):
"""
Prints a section of binary data in a hex editor-like format with highlighting.
Args:
data (bytes): The data to print.
start_address (int): The absolute memory address of the first byte in 'data'.
highlight_offset (int): The offset within 'data' to start highlighting.
highlight_len (int): The number of bytes to highlight.
"""
print(f"\n{Fore.CYAN}--- Hex View ---")
print(f"{Fore.CYAN}Address Hex Data ASCII")
print(f"{Fore.CYAN}---------- ------------------------------------------- ----------------")
for i in range(0, len(data), 16):
# The part of the data for this line
chunk = data[i:i+16]
# Format the address
hex_addr = f"{start_address + i:08X}"
# Format the hex bytes
hex_parts = []
for j, byte in enumerate(chunk):
# Determine if this byte should be highlighted
is_highlighted = (i + j) >= highlight_offset and (i + j) < (highlight_offset + highlight_len)
if is_highlighted:
# Color for the bytes we are about to change
hex_parts.append(f"{Fore.LIGHTYELLOW_EX}{Back.RED}{byte:02X}{Style.RESET_ALL}")
else:
# Default color for other bytes
hex_parts.append(f"{Fore.WHITE}{byte:02X}")
# Pad the hex section to align properly if the line is short
hex_str = " ".join(hex_parts)
hex_str = f"{hex_str:<48}" # 16 bytes * 2 chars + 15 spaces = 47, so 48 is safe
# Format the ASCII representation
ascii_parts = []
for j, byte in enumerate(chunk):
is_highlighted = (i + j) >= highlight_offset and (i + j) < (highlight_offset + highlight_len)
char = chr(byte) if 32 <= byte <= 126 else '.'
if is_highlighted:
ascii_parts.append(f"{Fore.LIGHTYELLOW_EX}{Back.RED}{char}{Style.RESET_ALL}")
else:
ascii_parts.append(f"{Fore.LIGHTBLACK_EX}{char}")
ascii_str = "".join(ascii_parts)
print(f"{hex_addr} {hex_str} {ascii_str}")
print(f"{Fore.CYAN}---------------------------------------------------------\n")
def main():
"""Main function to run the patcher."""
parser = argparse.ArgumentParser(
description='Colorful hex patcher for modem binary files to enable IMEI writing.',
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('infile', help='Input binary file (e.g., nr_modem_a.bin)')
parser.add_argument(
'outfile',
nargs='?',
default='nr_modem_a.imei_patch.bin',
help='Output binary file (default: nr_modem_a.imei_patch.bin)'
)
args = parser.parse_args()
try:
with open(args.infile, 'rb') as f:
# Use bytearray to allow in-place modification
content = bytearray(f.read())
except FileNotFoundError:
print(f"{Fore.RED}Error: Input file not found at '{args.infile}'")
sys.exit(1)
print(f"{Fore.GREEN}[*] Searching for byte sequence: {' '.join(f'{b:02X}' for b in SEARCH_BYTES)}")
offset = content.find(SEARCH_BYTES)
if offset == -1:
print(f"{Fore.RED}Error: Byte sequence not found in '{args.infile}'")
sys.exit(1)
print(f"{Fore.GREEN}[+] Sequence found at offset: {offset:#06x} ({offset} decimal)")
# Prepare context for the hex view (32 bytes before and after)
context_start = max(0, offset - 32)
context_end = min(len(content), offset + len(SEARCH_BYTES) + 32)
context_data = content[context_start:context_end]
# The highlight offset is relative to the start of the context_data
highlight_rel_offset = offset - context_start
print(f"\n{Fore.YELLOW}Current bytes to be patched (highlighted in red):")
print_hex_view(context_data, context_start, highlight_rel_offset, len(SEARCH_BYTES))
print(f"{Fore.CYAN}Planned change:")
print(f" From: {Fore.RED}{' '.join(f'{b:02X}' for b in SEARCH_BYTES)}")
print(f" To: {Fore.GREEN}{' '.join(f'{b:02X}' for b in PATCHED_BYTES)}")
# --- User Confirmation ---
while True:
choice = input(f"{Fore.YELLOW}Do you want to apply this patch? (y/n): ").lower().strip()
if choice == 'y':
break
elif choice == 'n':
print(f"{Fore.LIGHTBLACK_EX}Patch cancelled by user. Exiting.")
sys.exit(0)
else:
print(f"{Fore.RED}Invalid input. Please enter 'y' or 'n'.")
# --- Apply Patch ---
print(f"\n{Fore.GREEN}[*] Applying patch...")
content[offset] = PATCH_BYTE
try:
with open(args.outfile, 'wb') as f:
f.write(content)
print(f"{Fore.GREEN}[+] Successfully patched!")
print(f"{Fore.GREEN}[+] Patched file saved to: {args.outfile}")
except IOError as e:
print(f"{Fore.RED}Error writing to output file '{args.outfile}': {e}")
sys.exit(1)
# --- Final Instructions ---
print("\n" + "="*60)
print(f"{Fore.CYAN}{Style.BRIGHT}PATCHING COMPLETE!")
print("="*60)
print(f"""
You can now flash the patched file ({args.outfile}) to your device.
After flashing, you can open engineer mode using the dialer code:
{Fore.YELLOW}*#*#83781#*#*{Style.RESET_ALL}
Then, navigate to the AT Command mode and type one of the following:
{Fore.GREEN}AT+SPIMEI=0,"NEW_IMEI"{Style.RESET_ALL}
(to write a new IMEI)
{Fore.LIGHTBLACK_EX}AT+SPIMEI=0,"OLD_IMEI"{Style.RESET_ALL}
(to reset the IMEI to the original value)
Replace {Fore.YELLOW}"NEW_IMEI"{Style.RESET_ALL} with your desired 15-digit IMEI.
""")
print("="*60)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment