import argparse
import textwrap
import shutil
import os
import struct
def get_args():
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent(''' A tool to recover raw img'''))
parser.add_argument('-img', required=True, dest='img',
help='INPUT: img with header, Parse N/E from it')
parser.add_argument('-raw', required=False, dest='raw',
help='INPUT: recovered raw img')
parser.add_argument('--rcvr', help="recover the raw img without header",
action="store_true")
return parser.parse_args()
def __write_raw_img(raw, img, code_len, max_copy_size):
raw.seek(0)
img.seek(0x2100)
rsv_len = min(code_len - 0x100, max_copy_size)
while rsv_len > 0:
chunk_size = 4096 if rsv_len > 4096 else rsv_len
read_buf = img.read(chunk_size)
if not read_buf:
break
raw.write(read_buf)
rsv_len -= len(read_buf)
def check_image_headered(file_path):
with open(file_path, 'rb') as f:
data = f.read(4)
if len(data) < 4:
return False
word = int.from_bytes(data, byteorder='little')
return word == 0x55aa55aa
def main():
args = get_args()
if not args.rcvr:
raise Exception("No operation found, do nothing")
tmp_file = args.raw + '.tmp'
if check_image_headered(args.img) == False:
shutil.copyfile(args.img, tmp_file)
else:
with open(args.img, 'rb') as img:
img.seek(0x478)
code_len = struct.unpack('<I', img.read(4))[0]
if code_len < 0x100:
raise ValueError(f"Invalid code_len: (0x{code_len:x}), must be >= 0x100")
file_size = img.seek(0, os.SEEK_END)
if code_len > file_size:
raise ValueError(f"Invalid code_len: (0x{code_len:x}), must be <= file size: (0x{file_size:x})")
max_copy_size = file_size - 0x2100
with open(tmp_file, 'wb+') as raw:
__write_raw_img(raw, img, code_len, max_copy_size)
shutil.copyfile(tmp_file, args.raw)
if os.path.exists(tmp_file):
os.remove(tmp_file)
if __name__ == '__main__':
main()