- import argparse
- import re
- import struct
-
- def parse_line(line):
- match = re.match(r'^\[([0-9A-Fa-f]{8})\]: ((?:[0-9A-Fa-f]{8} ){7}[0-9A-Fa-f]{8})$', line.strip())
- if not match:
- return None
- address_str, data_str = match.groups()
- address = int(address_str, 16)
- words = [int(w, 16) for w in data_str.strip().split()]
- return address, words
-
- def main():
- parser = argparse.ArgumentParser(description='Convert hex dump format to raw binary for Ghidra.')
- parser.add_argument('-i', '--input', required=True, help='Input .hex-style file')
- parser.add_argument('-o', '--output', required=True, help='Output binary file')
- parser.add_argument('--base', type=lambda x: int(x, 16), default=None,
- help='Optional: base address override (hex, e.g. 0x08000000)')
- args = parser.parse_args()
-
- memory = {}
- min_address = None
- max_address = None
-
- with open(args.input, 'r') as infile:
- for line in infile:
- parsed = parse_line(line)
- if parsed is None:
- continue
- address, words = parsed
- for i, word in enumerate(words):
- addr = address + i * 4
- memory[addr] = word
- if min_address is None or addr < min_address:
- min_address = addr
- if max_address is None or addr > max_address:
- max_address = addr
-
- if args.base:
- min_address = args.base
-
- with open(args.output, 'wb') as outfile:
- addr = min_address
- while addr <= max_address:
- word = memory.get(addr, 0)
- outfile.write(struct.pack('<I', word)) # little-endian
- addr += 4
-
- if __name__ == '__main__':
- main()