vfsfitvnm / frida-il2cpp-bridge

A Frida module to dump, trace or hijack any Il2Cpp application at runtime, without needing the global-metadata.dat file.
https://github.com/vfsfitvnm/frida-il2cpp-bridge/wiki
MIT License
946 stars 194 forks source link

An issue with overriding methods #389

Closed n1ce0n3 closed 11 months ago

n1ce0n3 commented 11 months ago

I am currently trying to inspect arguments that are sent to a function, since I'm debugging in the runtime, I don't really enjoy compiling a script each time a make a change, so I use a compiled .js script instead via frida's REPL.

So the issue I am currently experiencing is this:

Il2Cpp.perform(() => {
    const assem = globalThis.assem = Il2Cpp.domain.assembly("Assembly-CSharp").image;
    const setAccountId = assem.class("LoginBeLimitedResponse").method("set_account_id");
    setAccountId.implementation = function (value) {
        const result = this.method("set_account_id").invoke(value);
        console.log(result);
        return result
    }
});

What I get as an output:

il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FileDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.FieldDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)
il2cpp: couldn't find method set_account_id in class Google.Protobuf.Reflection.EnumValueDescriptorProto
    at method (index.js:1778)
    at method (index.js:2620)
    at <anonymous> (<input>:5)
    at call (native)
    at <anonymous> (index.js:2529)

So apparently, it is considering "this" every instance of a class, instead of doing a check whether the current class is an instance of a required class.

Am I doing something wrong? Can it be caused by me using a compiled module within a REPL? Please, halp. Thanks in advance. <3

n1ce0n3 commented 11 months ago

Tried compiling both with frida-compile and esbuild - the same issue occurs. Replacing arrow functions for normal functions didn't help either.

vfsfitvnm commented 11 months ago

Thanks for reporting. What's the app name and steps to reproduce so that I can debug it on my own?

n1ce0n3 commented 11 months ago

@vfsfitvnm I can send you the app details (and the instructions how to launch it without anti-cheat, so you can actually attach frida ;) ), but AFAIK there is no "private messages" on github, so please, leave your discord here so I can add you (if you don't mind), I wouldn't really want the apps' developers' spies to notice this post and make it even harder for us to dump the damn game :) Though, you will still have to download a 35GB client to launch the game, I doubt that sending the binaries would do it, right? Also, if you want - we can share screen via discord/teamviewer so you don't have to go through the downloading process.

vfsfitvnm commented 11 months ago

@n1ce0n3 Sure, it's vfsfitvnm on discord

vfsfitvnm commented 11 months ago

It turns out frida-il2cpp-bridge is working correctly.

It looks like there are many methods (in different classes, but with the same signature) that have the same offset (and so the same virtual address). Hence, it is a many-to-one relationship, and re-implementing one of those methods ends up overriding the implementation for the others as well.

In practice, the object instance can belong to different (unrelated) classes, hence the couldn't find method error.

I don't know if there's something I can do to handle this scenario, but you could add a check like this:

const Method: Il2Cpp.Method = ...;
Method.implementation = function (...args) {
    if (Method.class.isAssignableFrom((this as Il2Cpp.Object).class)) {
        // your code here
    } else {
        return (Method as any).invokeRaw(this, ...args);
    }
};
n1ce0n3 commented 11 months ago

Thanks, sir. Keep up the good work <3