#!/usr/bin/env python3 """Wait for FIFA17.exe, then dump + disassemble the unpacked code around a VA. FIFA17.exe is packed on disk but Wine maps it flat at 0x140000000 and it unpacks at load, so the only way to read the real instructions is from a LIVE process (/proc//mem, needs ptrace_scope=0 -- openfut-fut.sh's root_arm does that). The game does NOT need to be at the crash point; the code is mapped as soon as the module is up. Usage: grab_crash_code.py [va_hex] [nbytes_before] [nbytes_after] Default VA is the 2026-08-03 create-club crash site FIFA17.exe+0x71b8651. """ import glob, os, sys, time VA = int(sys.argv[1], 16) if len(sys.argv) > 1 else 0x1471B8651 BEFORE = int(sys.argv[2]) if len(sys.argv) > 2 else 0xC0 AFTER = int(sys.argv[3]) if len(sys.argv) > 3 else 0x60 OUT = "/tmp/crash_code.txt" def find_pid(): for d in glob.glob("/proc/[0-9]*"): try: if open(d + "/comm").read().strip() == "FIFA17.exe": return int(d.split("/")[-1]) except Exception: pass return None print("waiting for FIFA17.exe (launch the game; no need to reach the crash)...", flush=True) pid = None while pid is None: pid = find_pid() if pid is None: time.sleep(2) print("pid=%d, reading %#x" % (pid, VA), flush=True) # give the unpacker a moment after process start time.sleep(5) start = VA - BEFORE with open("/proc/%d/mem" % pid, "rb") as f: f.seek(start) data = f.read(BEFORE + AFTER) lines = ["pid=%d window %#x..%#x (%d bytes)" % (pid, start, start + len(data), len(data)), "raw: " + data.hex()] try: import capstone md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) md.detail = False # align: disassemble from several offsets, keep the run that lands exactly on VA best = None for skip in range(0, 16): ins = list(md.disasm(data[skip:], start + skip)) if any(i.address == VA for i in ins): if best is None or len(ins) > len(best[1]): best = (skip, ins) if best: for i in best[1]: mark = " <<<<< FAULT (read from 0x0)" if i.address == VA else "" lines.append(" %#x %-10s %s%s" % (i.address, i.mnemonic, i.op_str, mark)) else: lines.append("could not align a disassembly onto the fault VA") except ImportError: lines.append("(capstone not installed; raw bytes above)") open(OUT, "w").write("\n".join(lines) + "\n") print("\n".join(lines)) print("\nwrote " + OUT)