import binascii
import hashlib
import struct
class ChunkParser:
def __init__(self):
self.chunkdata_partition_tlv_type = 0x01
self.chunkdata_cmd_tlv_type = 0x02
self.chunkdata_value_tlv_type = 0x03
self.chunkhash_info_tlv_type = 0x04
self.chunkdata_partiton_fmt = '<HH'
self.chunkdata_cmd_fmt = '<HH'
self.chunkdata_data_fmt = '<HI'
self.chunkhash_header_fmt = '<3H'
self.chunkhash_data_fmt = '<HH'
self.chunksign_value_fmt = '<HI'
def parse_chunklist(self, package_file, offset):
print(f'start read chunklist offset:{offset}')
package_file.seek(offset)
while True:
partition_data = package_file.read(struct.calcsize(self.chunkdata_partiton_fmt))
print(f'partition_data:{partition_data}')
if not partition_data:
break
partition_type, partition_length = struct.unpack(self.chunkdata_partiton_fmt, partition_data[:4])
partition_name = package_file.read(partition_length).decode('utf-8')
print(f"Partition Type: {partition_type}, Partition Name: {partition_name}")
if(partition_type != 18):
print(f'stop read chunklist')
break
cmd_data = package_file.read(struct.calcsize(self.chunkdata_cmd_fmt))
cmd_type, cmd_length = struct.unpack(self.chunkdata_cmd_fmt, cmd_data[:4])
cmd_info = package_file.read(cmd_length).decode('utf-8')
print(f"Command Type: {cmd_type}, Command Info: {cmd_info}")
data_data = package_file.read(struct.calcsize(self.chunkdata_data_fmt))
print(f'self.chunkdata_data_fmt :{data_data}')
data_type, data_length = struct.unpack(self.chunkdata_data_fmt, data_data[:6])
data_value = package_file.read(data_length)
print(f"Data Type: {data_type}, Data Length: {data_length}, Data Value: {data_value}")
if 'pkgdiff' in cmd_info:
with open('new_patch.dat', 'ab') as patch_file:
patch_file.write(data_value)
elif 'new' in cmd_info:
with open('new_new.dat', 'ab') as new_file:
new_file.write(data_value)
with open('new_transfer.list', 'ab') as list_file:
list_file.write((cmd_info + '\n').encode())
def parse_hash_info(self, package_file, offset):
print(f'start read hash_info offset:{offset}')
package_file.seek(offset)
while True:
hash_info_data = package_file.read(struct.calcsize(self.chunkhash_header_fmt))
if not hash_info_data:
break
hash_type, num_images, image_number = struct.unpack(self.chunkhash_header_fmt, hash_info_data)
print(f"Hash Type: {hash_type}, Number of Images: {num_images}, Image Number: {image_number}")
if(hash_type != 22):
print(f'stop read hash_info offset')
break
def parse_hash_data(self, package_file, offset):
print(f'start read hash_data offset:{offset}')
package_file.seek(offset)
while True:
partition_data = package_file.read(struct.calcsize(self.chunkdata_partiton_fmt))
print(f'partition_data:{partition_data}')
if not partition_data:
break
partition_type, partition_length = struct.unpack(self.chunkdata_partiton_fmt, partition_data[:4])
if(partition_type != 23):
print(f'stop read hash_data offset')
break
partition_name = package_file.read(partition_length).decode('utf-8')
print(f"Partition Type: {partition_type}, Partition Name: {partition_name}")
hash_data = package_file.read(struct.calcsize(self.chunkhash_data_fmt))
print(f'self.chunkdata_data_fmt :{hash_data}')
data_type, data_length = struct.unpack(self.chunkhash_data_fmt, hash_data[:4])
data_value = package_file.read(data_length)
print(f"Data Type: {data_type}, Data Length: {data_length}, Data Value: {data_value}")
large_data = package_file.read(struct.calcsize('<2HI'))
print(f'self.chunkdata_data_fmt :{large_data}')
large_data_type, large_data_length, large_data_value = struct.unpack('<2HI', large_data[:8])
print(f"image large Type: {large_data_type}, image large Length: {large_data_length}, image large Value: {large_data_value}")
with open('new_hash.txt', 'ab') as file:
file.write(data_value)
def parse_full_sign(self, package_file, offset):
print(f'start read full image sign offset:{offset}')
package_file.seek(offset)
while True:
sign_data = package_file.read(struct.calcsize(self.CHUNK_SIGN_VALUE_FMT))
print(f'self.chunkdata_data_fmt :{sign_data}')
data_type, data_length = struct.unpack(self.CHUNK_SIGN_VALUE_FMT, sign_data[:6])
data_value = package_file.read(data_length)
print(f"Data Type: {data_type}, Data Length: {data_length}, Data Value: {data_value}")
if(data_type != 26):
print(f'stop read full image sign')
break
with open('new_sign.txt', 'ab') as file:
hex_data = binascii.hexlify(data_value)
file.write(hex_data + b'\n')
def parse_full_stream(self, package_file, offset):
print(f'start read full stream offset:{offset}')
package_file.seek(offset)
while True:
partition_name = package_file.read(struct.calcsize(self.chunkdata_partiton_fmt))
print(f'self.chunkdata_data_fmt :{partition_name}')
partition_type, partition_length = struct.unpack(self.chunkdata_partiton_fmt, partition_name[:4])
partiton_value = package_file.read(partition_length)
print(f"Data Type: {partition_type}, Data Length: {partition_length}, Data Value: {partiton_value}")
if(partition_type != 18):
print(f'stop read full image')
break
cmd = package_file.read(struct.calcsize(self.chunkdata_partiton_fmt))
print(f'self.chunkdata_data_fmt :{cmd}')
cmd_type, cmd_length = struct.unpack(self.chunkdata_partiton_fmt, cmd[:4])
cmd_value = package_file.read(cmd_length).decode('utf-8')
print(f"Data Type: {cmd_type}, Data Length: {cmd_length}, Data Value: {cmd_value}")
with open('new_full.list', 'ab') as file:
file.write((cmd_value + '\n').encode())
image_data = package_file.read(struct.calcsize(self.chunkdata_data_fmt))
data_type, data_length = struct.unpack(self.chunkdata_data_fmt, image_data[:6])
data_value = package_file.read(data_length)
with open('new_iamge.img', 'ab') as file:
file.write(data_value)
def get_file_sha256(update_package):
sha256obj = hashlib.sha256()
maxbuf = 8192
with open(update_package, 'rb') as package_file:
while True:
buf = package_file.read(maxbuf)
if not buf:
break
sha256obj.update(buf)
hash_value_hex = sha256obj.hexdigest()
hash_value = sha256obj.digest()
return str(hash_value_hex).upper()
def calculate_file_hash(file_path):
hash_sha256 = hashlib.sha256()
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_sha256.update(chunk)
return hash_sha256.hexdigest()
def read_update_bin(file_path):
with open(file_path, 'rb') as f:
return f.read()
def parse_update_bin(data, offsets):
parsed_data = {}
for name, (offset, length) in offsets.items():
parsed_data[name] = data[offset:offset + length]
return parsed_data
def reconstruct_patch(parsed_data):
patch = b''
for name in parsed_data:
patch += parsed_data[name]
return patch
def verify_patch(original_patch, reconstructed_patch):
return original_patch == reconstructed_patch
def main():
chunk_parser = ChunkParser()
with open('update.bin', 'rb') as package_file:
chunk_parser.parse_chunklist(package_file, 632)
chunk_parser.parse_hash_info(package_file, 21590734)
chunk_parser.parse_hash_data(package_file, 21590740)
chunk_parser.parse_full_sign(package_file, 21590922)
if __name__ == "__main__":
main()