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

Read Argument Values #567

Open
Ezriral opened this issue Nov 9, 2024 · 1 comment
Open

Read Argument Values #567

Ezriral opened this issue Nov 9, 2024 · 1 comment
Labels
question A question about anything

Comments

@Ezriral
Copy link

Ezriral commented Nov 9, 2024

What i would like to know is how can i read for example here the MemoryStream of the argument.
This code is just an example (and wrong) what i tried but cannot get it working.
Would be happy if someone could tell me how to hook a specific function

.filterClasses(clazz => clazz.name.toLowerCase().includes("player"))
          .filterMethods(method => method.name.toLowerCase().includes("position"))

and the function has one argument "m = System.IO.MemoryStream"
and i want to read the bytes of it.

Il2Cpp.perform(() => {
      console.log("Unity Version: " + Il2Cpp.unityVersion);

      // Trace all methods in Assembly-CSharp containing "serialize" in the name
      var trace = Il2Cpp.trace(true)
          .assemblies(Il2Cpp.domain.assembly("Assembly-CSharp"))
          .filterClasses(clazz => clazz.name.toLowerCase().includes("player"))
          .filterMethods(method => method.name.toLowerCase().includes("position"))
          .and()
          .attach();

      // Hook each serialize method
      trace.on('enter', function(args) {
          // Check if any of the arguments are an instance of MemoryStream
          for (let i = 0; i < this.method.parameterCount; i++) {
              const paramType = this.method.parameterType(i);
              if (paramType.name.includes("MemoryStream")) {
                  const memoryStream = new Il2Cpp.Object(args[i]);

                  console.log("MemoryStream passed to " + this.method.name);

                  // Read the internal buffer of MemoryStream (using internal fields/methods)
                  const buffer = memoryStream.field("internalBuffer").value;
                  const position = memoryStream.field("position").value;
                  const length = memoryStream.field("length").value;

                  console.log(`MemoryStream internal buffer at position ${position}, length ${length}`);

                  // Optionally, read the buffer data
                  const bufferContent = buffer.readByteArray(length);
                  console.log("Buffer Content (in bytes):");

                  // Print the buffer content as a hex string
                  let hexString = "";
                  for (let i = 0; i < bufferContent.length; i++) {
                      hexString += bufferContent[i].toString(16).padStart(2, '0') + " ";
                  }
                  console.log(hexString);

                  break; // Stop once MemoryStream is found
              }
          }
      });

      trace.on('leave', function(retval) {
          console.log("Method " + this.method.name + " finished.");
      });
  });

Thank you

@Ezriral Ezriral changed the title Arguments Values Read Argument Values Nov 9, 2024
@vfsfitvnm vfsfitvnm added the question A question about anything label Nov 21, 2024
@vfsfitvnm
Copy link
Owner

Il2Cpp.Tracer is designed to quickly trace the invocation of a bulk of methods. Currently, it's not possible to pass a custom printer for a certain Il2Cpp.Type (but this could be a nice to have feature!).

If know in advance the method you want to hook, you should override the implementation of the specific method you want to hook and supply the logic to dump the MemoryStream.

PS: trace.on doesn't exist

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

No branches or pull requests

2 participants