Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve state of virtual Xbox via memory inspection #19

Open
JayFoxRox opened this issue Jul 12, 2018 · 0 comments
Open

Retrieve state of virtual Xbox via memory inspection #19

JayFoxRox opened this issue Jul 12, 2018 · 0 comments

Comments

@JayFoxRox
Copy link
Member

JayFoxRox commented Jul 12, 2018

Keep in mind that XQEMU is LLE and we can't always assume that it's running the official MS bios / kernel / licensed games. Anything which makes such assumptions is part of HLE.
HLE in XQEMU and its UI should always be entirely optional and it must be possible to disable such features (or they must handle non-MS code gracefully).


Following is some code which could be used to get information about the running XBE.
For more information, check http://xboxdevwiki.net/Xbe which also has a link to the file format at the bottom.

  • Doesn't handle bad XBEs gracefully and does no bounds checking.
  • Retrieves the information in multiple steps which might be problematic if the XBE is changed during readback.
  • Timestamp conversion could be broken.
  • Unicode conversion could be broken.
  • Not known wether it runs synchronously or asynchronously.
  • Written for Python 3, whereas XQEMU-Manager also supports Python 2.

Function to do HMP commands via QMP:

def read(self, addr, size):
  cmd = {
      "execute": "human-monitor-command", 
      "arguments": { "command-line": "x /%dxb %d" % (size,addr) }
  }
  response = self.run_cmd(cmd)
  lines = response['return'].replace('\r', '').split('\n')
  data_string = ' '.join(l.partition(': ')[2] for l in lines).strip()
  data = bytes(int(b, 16) for b in data_string.split(' '))
  return data

Code to read, parse and print XBE fields:

base = 0x00010000
if t.read(base, 4) == b'XBEH':
  xbe_timestamp = int.from_bytes(t.read(base + 0x114, 4), 'little')
  ts = datetime.datetime.utcfromtimestamp(xbe_timestamp)
  print("XBE Timestamp: %s (0x%08X)" % (str(ts), xbe_timestamp))

  cert_address = int.from_bytes(t.read(base + 0x118, 4), 'little')

  cert_timestamp = int.from_bytes(t.read(cert_address + 0x4, 4), 'little')
  ts = datetime.datetime.utcfromtimestamp(cert_timestamp)
  print("XBE Certificate Timestamp: %s (0x%08X)" % (str(ts), cert_timestamp))

  title_id = int.from_bytes(t.read(cert_address + 0x8, 4), 'little')
  a = title_id >> 24
  b = (title_id >> 16) & 0xFF
  i = title_id & 0xFFFF
  print('XBE Title-ID: 0x%X (%c%c-%03d)' % (title_id, a, b, i))

  title_name = t.read(cert_address + 0xC, 40 * 2).decode('utf-8')
  print("XBE Title-Name: '%s'" % title_name)
else:
  print("No XBE found")

Output:

XBE Timestamp: 2001-12-12 19:15:05 (0x3C17ACB9)
XBE Certificate Timestamp: 2002-03-04 15:58:09 (0x3C839991)
XBE Title-ID: 0x4D530007 (MS-007)
XBE Title-Name: 'Azurik - Rise of Perathia'

The primary use of this information would probably be that it could be displayed as part of the UI (possibly move it into the QEMU window title). This would be immediately visible for use in bug reports.

If we allow some kind of telemetry or motivate users to report often, we can also use this information to create a complete set of XBE header dumps / complete gameset, possibly discovering undumped DVDs.
A sneaky way to get telemetry could be rich presence (which I don't want for XQEMU) or pairing players for network games in the future (which I want, regardless of telemetry).


The memory-read gadget can also retrieve kernel information for bug reports.
Otherwise, it's quite limited in use, because the UI can get information directly through our hardware-emulation.

Reminder: Xbox RAM contains copyrighted or otherwise protected material during runtime. So I'd advise against doing full crashdumps.
We should selectively dump the metadata we need, much like the code above does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant