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 set_bytes(buf, off, blob): buf[off:off + len(blob)] = blob def set_u16(buf, off, value): buf[off] = value & 0xFF buf[off + 1] = (value >> 8) & 0xFF def main(): data = bytearray(Path(r'd:\Ghidra\Crusader\REGRET.EXE').read_bytes()) cleanup_off = 0xD2840 cleanup = bytes.fromhex( '55 8B EC 8B 46 06 0B 46 08 75 14 6A 26 9A FF FF 00 00 83 C4 02 89 56 08 89 46 06 0B C2 74 38 C4 5E 06 26 C7 47 08 00 00 26 C7 47 06 00 00 26 C7 47 04 00 00 26 C7 47 02 00 00 26 C7 07 FF FF 26 C7 47 20 00 00 26 C7 47 1E 00 00 26 C7 47 24 00 00 26 C7 47 22 00 00 8B 56 08 8B 46 06 5D CB 55 8B EC 56 8B 76 0A 8B 46 06 0B 46 08 74 2C C4 5E 06 26 C7 07 98 02 FF 76 08 53' ) set_bytes(data, cleanup_off, cleanup) code_off = 0xD28DD code = bytes.fromhex( '55 8B EC 50 52 53 56 57 06 A1 2C 71 8B 16 2E 71 0B C2 75 05 9A FF FF 00 00 A1 2C 71 8B 16 2E 71 0B C2 74 0A 52 50 9A FF FF 00 00 83 C4 04 9A FF FF 00 00 07 5F 5E 5B 5A 58 5D CB 00 8B 46 06 05 28 00 FF 76 08 50 9A FF FF 00 00 83 C4 06 6A 02 8B 46 06 05 1E 00 FF 76 08 50 9A FF FF 00 00 83 C4 06 F7 C6 01 00 74 10 FF 76 08 FF 76 06 9A FF FF 00 00 83 C4 04 EB 02 EB 00 5E' ) set_bytes(data, code_off, code) reloc_patches = { 0xD2C94: bytes.fromhex('03 00 FB 10 7F 00 8B 03'), 0xD2E0C: bytes.fromhex('03 00 4E 20 01 00 B4 36'), 0xD2E14: bytes.fromhex('03 00 CF 20 01 00 51 31'), 0xD2E1C: bytes.fromhex('03 00 BB 20 56 00 94 03'), 0xD2E3C: bytes.fromhex('03 00 F2 20 74 00 00 00'), 0xD2E34: bytes.fromhex('03 00 04 21 7D 00 19 04'), 0xD2E2C: bytes.fromhex('03 00 0C 21 74 00 0D 02'), 0x7BB25: bytes.fromhex('03 00 79 36 74 00 00 00'), 0x7BB15: bytes.fromhex('03 00 C1 36 80 00 DD 20'), 0x7BB05: bytes.fromhex('03 00 03 37 80 00 DD 20'), 0x7BAF5: bytes.fromhex('03 00 44 37 80 00 DD 20'), } for off, blob in reloc_patches.items(): set_bytes(data, off, blob) # Simulate relocation fixups for segment 13f8 and 1148 sites we changed. # Internal ref type 3 writes target offset and target selector into the 4-byte operand. relocs = [ 0xD2C94, 0xD2E0C, 0xD2E1C, 0xD2E14, 0xD2E2C, 0xD2E34, 0xD2E3C, 0x7BB25, 0x7BB15, 0x7BB05, 0x7BAF5, ] seg13f8_file = 0xD0800 seg1148_file = 0x76E00 for rec_off in relocs: rec = data[rec_off:rec_off + 8] src = u16(rec, 2) target_seg = rec[4] target_off = u16(rec, 6) if rec_off >= 0xD2C94: base = seg13f8_file else: base = seg1148_file op_off = base + src selector = 0x1000 + ((target_seg - 1) << 3) set_u16(data, op_off, target_off) set_u16(data, op_off + 2, selector) cleanup_loaded = data[0xD2840:0xD28BA] helper_loaded = data[0xD28DD:0xD2958] print('cleanup_loaded=', cleanup_loaded.hex(' ')) print('helper_loaded=', helper_loaded.hex(' ')) print('call_10fa=', data[0xD18FA:0xD18FF].hex(' ')) print('call_20f1=', data[0xD28F1:0xD28F6].hex(' ')) print('call_2103=', data[0xD2903:0xD2908].hex(' ')) print('call_210b=', data[0xD290B:0xD2910].hex(' ')) print('call_3678=', data[0x7A478:0x7A47D].hex(' ')) print('call_36c0=', data[0x7A4C0:0x7A4C5].hex(' ')) print('call_3702=', data[0x7A502:0x7A507].hex(' ')) print('call_3743=', data[0x7A543:0x7A548].hex(' ')) if __name__ == '__main__': main()