In an iOS app I have hooked an ObjC method that is getting an NSDictionary as argument.
I want to extract this data using Frida's send(message, data)
to the Frida client on the PC to process this data.
This NSDictionary seem to contain strings and numbers so converting it to JSON should be no problem.
The main problem is that you can not directly send an NSDictonary using the send
method. It would be possible to send the NSDictionary String representation instead of "mymessage"
but this String representation is not following any known standard which makes it difficult to parse it back to a dictionary or JSON representation.
Interceptor.attach(ObjC.classes.SomeClass['- someMethod:'].implementation, {
onEnter: function (args) {
let nsDictArg = new ObjC.Object(args[2]); // NSDictionary
// console.log(nsDictArg);
nsDictArg_converted = // How to convert NSDictionary so that it can be sent?
send("mymessage", nsDictArg_converted); // directly sending nsDictArg does not work
}
});
How can I convert the NSDictionary argument to a standardized format like JSON so hat I can sent it using the send
method back to the Frida client and there decode it?
I found a way using NSJSONSerialization
:
Interceptor.attach(ObjC.classes.SomeClass['- someMethod:'].implementation, {
onEnter: function (args) {
let nsDictArg = new ObjC.Object(args[2]); // NSDictionary
// convert nsDictArg to JSON
let err = ptr(ObjC.classes.NSError.alloc())
let json = ObjC.classes.NSJSONSerialization.dataWithJSONObject_options_error_(nsDictArg , 0, err);
// let jsonStr = json.bytes().readUtf8String(json.length());
let jsonBinary = json.bytes().readByteArray(json.length());
// Send JSON data back to Frida
send("mymessage", jsonBinary);
}
});
The advantage of this code is that it is not limited to NSDictionary
values. NSArray
values can also be converted to JSON and sent to the Frida on PC side.
Furthermore all data types NSJSONSerialization
supports for JSON serialization can be used this way.