Closed Chensem closed 2 years ago
Sure, you need to call inflate
:
const obj = JsonMapper.method("ToObject").overload("System.String").inflate(MessageClass).invoke(Return);
i think you misunderstand my meanings ?
the function ToObject return generic value and paramer's type is System.String , in frida-il2cpp-bridge is Il2Cpp.String
const obj = JsonMapper.method("ToObject").overload("System.String").inflate(MessageClass).invoke(Return);
i think this snippet , represent the input paramter is generic ?
i want to turn the return object to another object , like type cast ?
i evaluate your snippet and get the error below ? In dump.cs , there are two functions i used one is ToJson , which serialize the System.Object to Json string the another ToObject , which deserialize the Json String to System.Object
so I Intercept a function that the input paramter is System.Object , so i use ToJson to serialize object to json string , then i do something in this json string , then i use ToObject function to turn this json string to the object that i intercept .
As you can see, ToObject
doesn't have an offset (there's no // 0x....
), which means it cannot be called as it is (as expected, because it's generic). So you need to inflate it first (i.e. pass an actual type, so it's not generic anymore). But that error is definitely unexpected.
i want to turn the return object to another object , like type cast ?
This is what the inflate is for. Type casting is not a thing and it doesn't make sense in this scenario (the deserializer needs to now the type, right?).
the another ToObject , which deserialize the Json String to System.Object
I can't see such function, the one you highlighted returns a LitJson.JsonData
.
What's the application id/name? So I can take a look
The apk download link : https://download.link
the snippets i used
var AssemblyCSharp = Il2Cpp.Domain.assembly("Assembly-CSharp").image;
var JsonMapper = AssemblyCSharp.class("LitJson.JsonMapper");
AssemblyCSharp.class("GameXX").method("SendMessage").implementation = function(message : Il2Cpp.Object) : void{
var tpe = message.method("GetType").invoke() as Il2Cpp.Object;
var MessageId = AssemblyCSharp.class("LiteNet.MessageMapping").method("GetMessageID").overload("System.Type").invoke(tpe) as Il2Cpp.Object;
if(MessageId.toString() == "XX"){
this.method("SendMessage").invoke(message)
}else{
// object to json string
var Return = JsonMapper.method<Il2Cpp.String>("ToJson").invoke(message)
console.warn(`return json string is ${Return}`)
// here want to convert json string to message
const Obj = JsonMapper.method("ToObject").overload("System.String").inflate(AssemblyCSharp.class("LiteNet.IMessage")).invoke(Return)
console.log(Obj) // want to convert to message object
this.method("SendMsg").invoke(Obj) // converted object
}
}
Thanks, but would you tell me the apk id (i.e. com.example.application
) instead of a direct apk download?
com.xxx.application
Ok, I got it.
This line
JsonMapper.method("ToObject").overload("System.String")
selects this method:
static LitJson.JsonData ToObject(System.String json); // 0x0126c040
That's why it complains it's not generic. Unfortunately there's an overload clash. So, to select this one:
static T ToObject(System.String json);
you can do:
const ToObject = JsonMapper.methods.find(candidate => candidate.toString() == "static T ToObject(System.String json);");
Full code:
import "frida-il2cpp-bridge";
Il2Cpp.perform(() => {
const AssemblyCSharp = Il2Cpp.Domain.assembly("Assembly-CSharp").image;
const JsonMapper = AssemblyCSharp.class("LitJson.JsonMapper");
const GetMessageID = AssemblyCSharp.class("LiteNet.MessageMapping").method<Il2Cpp.Object>("GetMessageID").overload("System.Type");
const ToObject = JsonMapper.methods.find(candidate => candidate.toString() == "static T ToObject(System.String json);")!.inflate<Il2Cpp.Object>(AssemblyCSharp.class("LiteNet.IMessage"));
console.log(ToObject);
AssemblyCSharp.class("GameNet").method("SendMsg").implementation = function (message: Il2Cpp.Object): void {
const type = message.method<Il2Cpp.Object>("GetType").invoke();
const messageId = GetMessageID.invoke(type);
if (messageId.toString() == "XX_RESPONSE_HEARTBEAT") {
this.method("SendMsg").invoke(message);
} else {
const result = JsonMapper.method<Il2Cpp.String>("ToJson").invoke(message);
console.log(`return json string is ${result}`);
const object = ToObject.invoke(result);
console.log(object);
this.method("SendMsg").invoke(object);
}
}
});
on my machine , abort was called ? when invoke
const object = ToObject.invoke(result);
I seem to know the reason LiteNet.IMessage is a interface
I didn't run the code because I needed to play the game. "Abort was called" means an exception occurred (you can put Il2Cpp.installExceptionListener("all");
somewhere so it will print that exception).
Yeah, indeed that may be the reason.
thank you quickly reply , it solved my problem , thank you so much .
Hey , I am some problem about return value convert the target function return value type is generic , can you show me snippet