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

'this' value of incorrect type #237

Closed
carmebar opened this issue Oct 18, 2022 · 10 comments
Closed

'this' value of incorrect type #237

carmebar opened this issue Oct 18, 2022 · 10 comments

Comments

@carmebar
Copy link

carmebar commented Oct 18, 2022

Probably related to #181.

UnityVersion: 2020.3.34f1
APK: [REDACTED]
Frida version: latest (16.0.1)
Frida server: latest (16.0.1) arm64
Compiled with: esbuild --bundle --outfile=_.js --watch index.ts
Running on: real hardware

import "frida-il2cpp-bridge";

Il2Cpp.perform(() => {
	const assem = Il2Cpp.Domain.assembly("Assembly-CSharp").image;
	const getRandomSeedID = assem.class("Seed").method("GetRandomSeedID");

	//System.Collections.Generic.Dictionary<System.String,System.String> GetRandomSeedID(System.String min, System.String max); // 0x013a7d50
	getRandomSeedID.implementation = function (min : Il2Cpp.String, max: Il2Cpp.String) : Il2Cpp.Pointer {
		return this.method<Il2Cpp.Pointer>("GetRandomSeedID").invoke(max, max);;
	};
});

il2cpp: couldn't find method GetRandomSeedID in String, did you mean GetHashCode?


getRandomSeedID.fridaSignature

pointer, pointer, pointer

	const replacement = new NativeCallback((instance, min, max) => {
		console.log("this:", new Il2Cpp.Object(instance));
		console.log("min:", new Il2Cpp.String(min));
		console.log("max:", new Il2Cpp.String(max));
		return new NativePointer(0);
	}, "pointer", ["pointer", "pointer", "pointer"]);

this: 3
min: "1"
max: "3"

Any indications on how to keep troubleshooting or any extra information that I can gather to help debug the issue?

Thank you for your time and work on the library. Much appreciated.

@carmebar
Copy link
Author

carmebar commented Oct 18, 2022

	Interceptor.attach(getRandomSeedID.virtualAddress, {
		onEnter(args) {
			console.log(args[0]);
			console.log(args[1]);
			console.log(args[2]);
			const min = new Il2Cpp.String(args[1]);
			const max = new Il2Cpp.String(args[2]);
			console.log(min);
			console.log(max);
		}
	});

0x724c699f40
0x724c699f60
0x724c699f40
"1"
"3"

args[0] and args[2] are the same address... Issue with frida? Any guidance to further debug?

At the moment I'm able to just change args[1] and args[2] to change the behaviour in the way I wanted. Just wondering if its an issue with the library or I'm doing something wrong.

@vfsfitvnm
Copy link
Owner

Thanks for the report. Would you try an older Frida version (15.x)?

@carmebar
Copy link
Author

Can confirm same issue.

frida --version
15.2.2

@vfsfitvnm
Copy link
Owner

Unfortunately the game won't load because it requires the google play services, which I don't have.
Put this code in the implementation: what does it print?

console.log(typeof this);
console.log(this instanceof Il2Cpp.Object);
if (this instanceof Il2Cpp.Object) {
    console.log(this.class.type.name);
}

@carmebar
Copy link
Author

Thank you for trying to run the APK.
Here's the output:

object
true
System.String

As expected by the pointers... 🤔

@vfsfitvnm
Copy link
Owner

vfsfitvnm commented Oct 19, 2022

There are two possibilities: GetRandomSeedID is either a static method (but I cannot detect it somehow) or it doesn't use this, so the compiler performed an optimization and made it static (only in practice). The former can be verified by getting the flags of the C# object of such method, the latter can be verified using a disassembler and looking at how many parameters are being passed (2 or 3). I personally think it's the latter

@carmebar
Copy link
Author

carmebar commented Oct 19, 2022

This is the whole definition of the class dumped by il2cpp-bridge (same signatures as the ones extracted with il2cppdumper from the binary):

// Assembly-CSharp
class Seed : System.Object
{
    Shop_PotList_Detail m_DetailView; // 0x10
    System.Int32 pot_id; // 0x18
    Cooltime LoadPotCoolTimeData; // 0x20
    System.DateTime coolTime; // 0x28
    System.TimeSpan cTime; // 0x30
    System.TimeSpan totalT; // 0x38
    System.Int32 totalTime; // 0x40
    System.Boolean UpdateTime; // 0x44
    System.String load_show_str; // 0x48
    System.Boolean m_EventSeed; // 0x50
    System.Collections.Generic.Dictionary<System.String,System.String> getDB; // 0x58
    System.String selectSeedIndex; // 0x60
    System.Action onCompleteShowInfoHandler; // 0x68
    System.String UpdateGroupSeedString; // 0x70
    System.Void .ctor(Shop_PotList_Detail arg_obj_DetailView, System.Int32 arg_PotID, System.String arg_seedIndex, System.Boolean arg_Event); // 0x013a5184
    System.Void ShowInfo(System.Action _onCompleteShowInfoHandler); // 0x013b8b80
    System.Void BuyItem(); // 0x013b8b88
    System.Void PlantSeed(); // 0x013b8b8c
    System.Void PlantSeedAll(); // 0x013b8b90
    System.Void PlantSeedError(); // 0x013b8b94
    System.Void Update(); // 0x013b8b98
    System.Void SeedInfoDetail(); // 0x013a58c4
    System.Collections.Generic.Dictionary<System.String,System.String> GetGroupSeedID(System.String seed1, System.String seed2, System.String seed3, System.Int32 prob1, System.Int32 prob2, System.Int32 prob3); // 0x013a7b28
    System.Collections.Generic.Dictionary<System.String,System.String> GetRandomSeedID(System.String min, System.String max); // 0x013a7d50
    System.Boolean PurchasedAlready(); // 0x013b8eb0
    System.Void SaveNewUserDataResult(BuyIllustResult result); // 0x013b8fac
    System.Void OnComfirmSeedingNow(ClientConsts.ConfirmList _result); // 0x013b9abc
    System.Void SyncDataNow(); // 0x013b94b4
    System.Void SyncIllustData(); // 0x013b97b8
    System.Void GetUserDataResult(GetCurrencyResult result); // 0x013b9b50
    System.Void GetSeedResult(GetIllustResult result); // 0x013b9dd8
    System.Void Fail_Connect(System.Int32 result, System.String message); // 0x013a89e4
    System.Void Fail_ConnectSeeding(System.Int32 result, System.String message); // 0x013ba014
    System.Void ShowLoading(System.Boolean arg_Flag); // 0x013ba07c
}

And the decompiled method from Ghidra
image

Seems you are right about first param (this) not being used inside the method.

@vfsfitvnm
Copy link
Owner

vfsfitvnm commented Oct 19, 2022

So I would go for:

        const dummySeed = assem.class("Seed").alloc();
	getRandomSeedID.implementation = function (min : Il2Cpp.String, max: Il2Cpp.String) : Il2Cpp.Object {
		return dummySeed.method<Il2Cpp.Object>("GetRandomSeedID").invoke(max, max);;
	};

@carmebar
Copy link
Author

Yes, that works as expected. I am not able to cache the allocated class because sometimes it gets overriden by other classes and fails randomly with errors like:

il2cpp: couldn't find method GetRandomSeedID in TypeFilter, did you mean Invoke?

Thank you for walking me through the debugging. Hopefully this issue will help somebody in the future like the rest of issues helped me to learn the library 👍🏿

@vfsfitvnm
Copy link
Owner

I am not able to cache the allocated class because sometimes it gets overriden by other classes and fails randomly with errors like

Right! That occurs because dummySeed is allocated in the frida thread; but when the Il2Cpp.perform call ends, the frida thread gets detached from the il2cpp world, so the memory gets reassigned.

You could try:

        let dummySeed: Il2Cpp.Object?;
	getRandomSeedID.implementation = function (min : Il2Cpp.String, max: Il2Cpp.String) : Il2Cpp.Object {
	        if (dummySeed == null) dummySeed = assem.class("Seed").alloc();
		return dummySeed!.method<Il2Cpp.Object>("GetRandomSeedID").invoke(max, max);;
	};

or

        const dummySeed = assem.class("Seed").alloc();
        dummySeed.ref(true);
	getRandomSeedID.implementation = function (min : Il2Cpp.String, max: Il2Cpp.String) : Il2Cpp.Object {
		return dummySeed.method<Il2Cpp.Object>("GetRandomSeedID").invoke(max, max);;
	};

(#183 (comment)).

I am curious to know if both works!

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

2 participants