from pathlib import Path def u16(data, off): return data[off] | (data[off + 1] << 8) def u32(data, off): return u16(data, off) | (u16(data, off + 2) << 16) def get_segment(data, selector): ne_off = u32(data, 0x3C) seg_table_off = ne_off + u16(data, ne_off + 0x22) align_shift = u16(data, ne_off + 0x32) seg_index = ((selector - 0x1000) // 8) + 1 seg_entry_off = seg_table_off + (seg_index - 1) * 8 sector = u16(data, seg_entry_off) seg_len = u16(data, seg_entry_off + 2) if seg_len == 0: seg_len = 0x10000 seg_file_off = sector << align_shift return seg_file_off, seg_len def emit_runs(blob, seg_base, selector, allowed, minimum): start = None for i, byte in enumerate(blob): if byte in allowed: if start is None: start = i elif start is not None: length = i - start if length >= minimum: print(f'{selector:04X}:{start:04X} file=0x{seg_base + start:X} len=0x{length:X} bytes={blob[start:start+min(length,16)].hex(" ")}') start = None if start is not None: length = len(blob) - start if length >= minimum: print(f'{selector:04X}:{start:04X} file=0x{seg_base + start:X} len=0x{length:X} bytes={blob[start:start+min(length,16)].hex(" ")}') def main(): data = Path(r'd:\Ghidra\Crusader\REGRET.EXE').read_bytes() seg_base, seg_len = get_segment(data, 0x13F8) blob = data[seg_base:seg_base + seg_len] print(f'segment 13F8 file=0x{seg_base:X} len=0x{seg_len:X}') print('zero runs >= 0x20') emit_runs(blob, seg_base, 0x13F8, {0x00}, 0x20) print('nop/int3 runs >= 0x10') emit_runs(blob, seg_base, 0x13F8, {0x90, 0xCC}, 0x10) if __name__ == '__main__': main()