55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
|
|
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()
|