Skip to content

Instantly share code, notes, and snippets.

@Jaluanda
Forked from ndunks/zte_extract.py
Created March 8, 2020 17:05
Show Gist options
  • Save Jaluanda/d697385a6345be48eea46dfabd40e168 to your computer and use it in GitHub Desktop.
Save Jaluanda/d697385a6345be48eea46dfabd40e168 to your computer and use it in GitHub Desktop.
Modem Indihome ZTE F609 Config Extract and Repack
#!/usr/bin/env python
# https://reverseengineering.stackexchange.com/a/13395
import sys
import binascii
import struct
import zlib
if (len(sys.argv) <= 1):
print('USAGE:\n%s [configBak.cfg|config.bin]' % sys.argv[0])
exit(1)
cf = open(sys.argv[1], 'rb')
h = cf.read(0x4c)
#--------------------
# read the header
if (h[0:4] != '\x04\x03\x02\x01'):
print 'Invalid magic, Skip magic check, may this is default config stored on modem'
h2 = h
cf.seek(-0x10, 1)
else:
h2 = h[0x10:]
if (h2[0:0x4] != '\x01\x02\x03\x04'):
print 'Invalid magic'
sys.exit(-1)
hcrc_calc = binascii.crc32(h2[0:0x18])&0xffffffff
hcrc_store = struct.unpack('!L', h2[0x18:0x1c])[0]
print 'calc: %x - stored: %x'%(hcrc_calc, hcrc_store)
if (hcrc_calc != hcrc_store):
print 'Invalid header CRC'
sys.exit(-2)
block_buffer_size = struct.unpack('!L', h2[0x10:0x14])
# used to allocate memory for temp buffers
print 'block buffer size: %x' % block_buffer_size
# print 'block buffer size: %x, zlib_len, %x, config_len: %x'%(block_buffer_size, zlib_chunk_length, config_bin_length)
#--------------------
# read the blocks
fout = open('%s.xml'%(sys.argv[1]), 'wb')
cumulate_crc = 0
while (True):
bheader = cf.read(0x0c)
if (len(bheader) == 0):
break
(uncompressed_size, zlib_size, conf_len) = struct.unpack('>LLL', bheader)
print 'uncomp size: %x, zlib size: %x, cfg size: %x'%(uncompressed_size, zlib_size, conf_len)
# read the whole block to previously allocated buffer
# Possible heap based buffer overflow, because the size was not checked in
# the dbcCfgFileDecry function!
block = cf.read(zlib_size)
cumulate_crc = binascii.crc32(block, cumulate_crc)&0xffffffff
decompressed = zlib.decompress(block)
fout.write(decompressed)
stored_cumulate_crc = struct.unpack('!L', h2[0x14:0x18])[0]
print 'cumulate crc: calc: %x - stored: %x'%(cumulate_crc, stored_cumulate_crc)
if (cumulate_crc != stored_cumulate_crc):
print 'Invalid cumulate CRC'
sys.exit(-3)
cf.close()
fout.close()
print( 'Extracted as %s.xml' % sys.argv[1] )
#!/usr/bin/env python
# [email protected]
import re
import zlib
import struct
import binascii
import sys
if len(sys.argv) <= 1 :
print("USAGE:")
print("\t %s <config.xml>" % sys.argv[0])
exit(1)
block_size =0x10000
if len(sys.argv) == 3 :
block_size = 0x2000
print("Using sistem block size")
cumulate_crc = 0
crc_head = 0
# last_index = 2
last_uncompressed_size = 0
last_cfg_index = 0x3c2b
main_content = b''
index_counter = 0
conf_index = 0x3C
with open(sys.argv[1], 'rb') as f:
while True:
xml = f.read(block_size)
xml_len = len(xml)
zlib_xml = zlib.compress(xml, 9)
uncompressed_size =xml_len
zlib_size = len(zlib_xml)
last_uncompressed_size = xml_len
if xml_len < block_size:
# this last size
conf_index = 0
else:
conf_index += 12 + zlib_size
index_counter +=1
block_head = struct.pack('!LLL', uncompressed_size, zlib_size, conf_index)
cumulate_crc = binascii.crc32(zlib_xml, cumulate_crc) & 0xffffffff
main_content += block_head + zlib_xml
print("READ 0x%x, zlib_size: %x, conf index: %x" % (xml_len, zlib_size, conf_index) )
# this last size
if xml_len < block_size:
break
# 0 - 0x14 = Magic bytes
magic_bytes='\x04\x03\x02\x01'+ "\x00"*0x7 + "\x04F609" + '\x01\x02\x03\x04'
# 0x14 - 0x17 = Padding ?
h_padding = "\x00" * 0x4
#0x18 - 0x19 = Last Index ?
h_last_index = struct.pack('!h', index_counter)
#0x1a - 0x1b = Last uncompresed size ?
h_last_size = struct.pack('!h', last_uncompressed_size)
# 0x1c - 0x1d unknown
h_padding2 = "\x00" * 0x2
#0x1e - 0x1f = Last cfg index ?
h_last_cfg_index = struct.pack('!h', last_cfg_index)
#0x20 - 0x24 BLOCK SIZE
h_block_size = struct.pack('!L', block_size)
#0x24 - 0x28 - Content CRC
h_crc_content= struct.pack('!L', cumulate_crc)
content_header = magic_bytes + h_padding + h_last_index + h_last_size + h_padding2 + \
h_last_cfg_index + h_block_size + h_crc_content
#0x28 - 0x2c - Header CRC
crc_head = binascii.crc32(content_header[0x10:0x28])&0xffffffff
h_padding3 = "\x00" * 0x20
h_crc_head = struct.pack('!L', crc_head )
print("Content CRC: %x" % cumulate_crc )
print('Head CRC: %x' % crc_head)
with open('%s.bin' % sys.argv[1], 'wb') as f:
f.write( content_header + h_crc_head + h_padding3 + main_content )
print('Packed as %s.bin' % sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment