verify_ember_movie_native.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. """Offline ABI verification against a mapped/decrypted image, never an on-disk encrypted EXE.
  2. Usage: python3 tests/verify_ember_movie_native.py path/to/game_image.bin
  3. """
  4. import re
  5. import struct
  6. import sys
  7. from pathlib import Path
  8. repo = Path(__file__).resolve().parents[1]
  9. data = Path(sys.argv[1]).read_bytes()
  10. def signature(file, name):
  11. source = (repo / file).read_text()
  12. pattern = re.search(r'constexpr auto ' + name + r'\s*=\s*signature<signature_length\("([^"]+)"\)', source)[1]
  13. regex = b''.join(b'.' if token == '?' else re.escape(bytes([int(token, 16)])) for token in pattern.split())
  14. matches = [m.start() for m in re.finditer(regex, data, re.S)]
  15. assert len(matches) == 1, (name, matches)
  16. return matches[0]
  17. def target(base, offset, expected):
  18. assert data[base + offset] == 0xE8
  19. value = base + offset + 5 + struct.unpack_from('<i', data, base + offset + 1)[0]
  20. assert value == expected, (hex(base), hex(offset), hex(value), hex(expected))
  21. path = 'Sunrise/src/client/hooks/ember_movies/resources.cpp'
  22. load = signature(path, 'loadSig')
  23. end = signature(path, 'endSig')
  24. assert load == 0xB46E10 and end == 0xB44020
  25. for offset, expected in [(0x96, 0x4294D0), (0xD1, 0x423EF0), (0x14C, 0x4312D0), (0x157, 0x435AA0)]:
  26. target(load, offset, expected)
  27. for offset, expected in [(0x85, 0x42C650), (0x9F, 0x425310)]:
  28. target(end, offset, expected)
  29. assert data[end + 0x2E:end + 0x31] == bytes.fromhex('48 8B 05')
  30. assert end + 0x35 + struct.unpack_from('<i', data, end + 0x31)[0] == 0x2439C70
  31. attach = signature('Sunrise/src/client/hooks/bootflow/ember_sunburn.cpp', 'sig')
  32. assert attach == 0x9F2760
  33. # Native attach dereferences the runtime relative template, then passes it to the child factory.
  34. target(attach, 0x68, 0x32BBD0)
  35. target(attach, 0x78, 0x56DE00)
  36. assert data[0x4AE000:0x4AE002] == bytes.fromhex('8B 09') # factory reads resource at request+0
  37. print('Native resource request / submit / status / release and sunburn attachment ABI verified.')