Skip to content

Instantly share code, notes, and snippets.

@ceres-c
Created December 21, 2025 17:38
Show Gist options
  • Select an option

  • Save ceres-c/1d5e777c57f74ff0975c9a4a4cdecbe1 to your computer and use it in GitHub Desktop.

Select an option

Save ceres-c/1d5e777c57f74ff0975c9a4a4cdecbe1 to your computer and use it in GitHub Desktop.
Playing around with the ZTE H6645P v2
from pathlib import Path
import sys
from Crypto.Cipher import AES # pycryptodome
def hc_get_ver_val(hardcode_path: Path, hardcoded_input_size: int) -> bytes | None:
"""
Python equivalent of the HCGetVerVal function.
Reads the hardcode file, strips newlines, and returns the bytes
constrained by hardcoded_input_size.
"""
with hardcode_path.open('rb') as f:
line = f.read(64)
if not line:
raise OSError(f"Can't read data from {hardcode_path}")
clean_line = line.splitlines()[0]
# Respect the destination buffer size (snprintf behavior)
return clean_line[:hardcoded_input_size]
def decrypt_file(input_file: Path, output_file: Path, key: bytes):
print(f"Decrypting {input_file} to {output_file}...")
try:
with input_file.open('rb') as f_in:
ciphertext = f_in.read()
cipher = AES.new(key, AES.MODE_ECB)
# The C code zero-padded the buffer, so we do the same if needed.
if len(ciphertext) % 16 != 0:
ciphertext = ciphertext.ljust(len(ciphertext) + (16 - len(ciphertext) % 16), b'\0')
decrypted_data = cipher.decrypt(ciphertext)
# The C code used strlen to determine output length, effectively stripping trailing nulls.
decrypted_data = decrypted_data.rstrip(b'\0')
with output_file.open('wb') as f_out:
f_out.write(decrypted_data)
print("Decryption complete.")
except Exception as e:
print(f"Decryption failed: {e}")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="Decrypt enhardcodefile.")
parser.add_argument("hardcode_file", type=Path, help="Path to the /etc/hardcode file")
parser.add_argument("encrypted_file", type=Path, help="Path to the encrypted file")
args = parser.parse_args()
hardcode_path = args.hardcode_file.resolve()
if not hardcode_path.exists():
print(f"Error: {hardcode_path} does not exist")
exit(1)
ver_val = hc_get_ver_val(hardcode_path, 0x20)
if not ver_val:
print(f"Could not read ver_val from {hardcode_path}")
exit(1)
key = b'0x18600x0001' + ver_val # 0x1860 and 0x0001 are hardcoded values found in 'CspHardCodeParamGet' in libhardcode.so
key = key.ljust(32, b'\0')
print(f"AES key: {key}")
# Try to decrypt the provided file
encrypted_path = args.encrypted_file.resolve()
decrypted_path = encrypted_path.parent / (encrypted_path.name + '_decrypted')
if encrypted_path.exists():
decrypt_file(encrypted_path, decrypted_path, key)
else:
print(f"File {encrypted_path} not found.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment