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

wip: generic MT DTI dumper w/ AOB-based vftable identification #1

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

Andoryuuta
Copy link
Owner

@Andoryuuta Andoryuuta commented Jul 24, 2022

Complete refactor of the project into a (more) universal MTFramework DTI dumper + related tooling.

In order to combat the crashing/instability issues of the current master branch, this refactoring opts for a new multi-tiered approach to dumping.

Associate DTI <-> vftables without class instantiation

In order to get the vftable for a given class without calling the constructor directly, we utilize the ::GetDTI virtual function to associate a DTI object with the vftable:

  1. Get the full list of DTI objects from the DTI table after static initializers have run.
  2. Scan the binary for the lea rax, <DTI OBJECT>; RET pattern used in all ::GetDTI methods.
  3. Find references to those potential ::GetDTI methods
  4. Walk backwards from those references to the vftable start.

NOTE: This still isn't perfect, as there are some methods that return DTI objects with this same pattern that are not the ::GetDTI method. Additionally, there are some classes that have inherited from a DTI class, but have not registered themselves in the DTI table / overriden the relevant virtual member functions.

Dumping property lists (safely)

To populate the property list for a given class, we must have a "valid" instance in memory to pass to the populate member function (as it tries to deference the pointer). To work around this without calling the constructor (for stability) we create a fake object (empty byte buffer the size of the class, as defined by the DTI) and set the first element the vftable.

When calling the ::CreateProperty function we sometimes run into certain cases where the vftable we found was incorrect (see note in section above), or has code that would othewise crash the process or hang the current thread (lock/mutex, loop, etc). The crashes can be prevented with a SEH handler, but the hanging calls pose issues.

If order to work around this, when attempting to dump the property list create a new thread with it's own SEH exception handler. If the thread does not signal completion within a certain period of time, we assume that the population has failed (either due to crash of hanging), kill the job thread, then continue.

TODO: We currently don't track which have failed for further evaluation. Create a ticket for this.

Separation of property dumping and processing

Rather than needing to run this dumper for every small formatting/output generator change, I've decided to split out dumping from the processing as much as possible. This was done by making the dumper only aware of the binary layout of each games structures (MtProperty, MtPropertyList, etc), and dumping the raw data to a JSON file.

This dump while large, convoluted, and unwieldy can be used more easily from external tooling (e.g. the process_dump.py script).

Example DTI dump and processing of MHW

  1. Ensure that the following are correct in src/MT/game/MHW.h:
  • MtProperty class definition
  • MT_DTI_HASH_TABLE_OFFSET
  • MT_TYPE_TABLE_RVA_OFFSET
  • MT_TYPE_TABLE_COUNT
  1. Ensure that the game profile at scripts/profiles/MHW.json is correct:
  • Text encoding
  • MT types
  1. Build the project & inject into MHW

  2. Process the raw dump with the script

py -3 scripts\process_dump.py "C:\Program Files (x86)\Steam\steamapps\common\Monster Hunter World\dti_map_with_props.json" scripts\profiles\MHW.json
  1. A flat_dump.h will be generated with a format similar to the original MHW-ClassPropDump project.
  • TODO: Handle getter/setter types
  • TODO: Handle array types

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

Successfully merging this pull request may close these issues.

None yet

1 participant