A, goals,

We are already familiar with using FRIda to calculate the signature of RPC calls in Android.

Today, I’ll show you how to play on IOS. The main points are as follows:

  • Parameter Type confirmation
  • NSDictionary NSArray and other ObjectC object construction and copy
  • ObjectC class method and object method calls
  • As a bonus, how is the nil argument to ObjectC constructed

Second, the steps

Refer to gameplay on Android

By referring to [some sub-APP protocol Analysis (iii)], we first set up the framework of FRIda RPC. The routine of this piece is the same.

  • Flask starts a Web service
  • The script exposes an interface for Python to call
app = Flask(__name__)

@app.route('/getSignFromJni', methods=['GET'])
def getSignFromJni():
    global gScript

    body = "{\"api-version\":\"1.1.0\"}"
    client = "apple"
    clientVersion = "10.0.1"
    functionId = "xview2Config"
    openudid = "078593ee2fda3d54aae5879cb841b2faa62a4985"
    
    res = gScript.exports.callsign(body,client,clientVersion,functionId,openudid)
    return res
Copy the code

For demonstration purposes, we create a GET interface here and write the argument dead. In practice, you can create a POST interface to pass parameters in.

rpc.exports = {
	callsign : callSignFun
};
Copy the code

The script exposes a callSign function for Python to call.

Parameter Type confirmation

+[XXSignService getSignWithDic:keys:] +[XXSignService getSignWithDic:keys:] +[XXSignService getSignWithDic:keys:] +[XXSignService getSignWithDic:keys:] has two arguments. Check out the cross-reference method again from last time.

Open IDA, a face meng force, yesterday forgot to save, yesterday forgot to save, forget to save……

Do you know IDA chewed it all morning yesterday? Are you going to chew it all morning?

Let’s try a different way, since we’ve already figured it out, use Frida to print the parameter types.

onEnter: function(args) {
        var receiver = new ObjC.Object(args[0]);

        var message1 = ObjC.Object(args[2]);
        var message2 = ObjC.Object(args[3]);

        console.log('msg1=' + message1.toString() + ",type: "+ message1.$className);
        console.log('msg2=' + message2.toString() + ",type: "+ message2.$className);

},
Copy the code

I knew Frida wouldn’t let us down

msg1={
    body = "{\"channel\":1,\"fQueryStamp\":\"1622690375496\"}";
    client = apple;
    clientVersion = "10.0.1";
    functionId = bubbleComponent;
    openudid = 078593ee2fda3d54aae5879cb841b2faa62a4985;
},type: __NSDictionaryI
msg2=(
    functionId,
    body,
    openudid,
    client,
    clientVersion
),type: __NSArrayI
Copy the code

Parameter 1 is of type NSDictionary, and parameter 2 is an array of strings, NSArray

Construct NSDictionary and NSArray

After all, we didn’t do ObjectC, so we had to program for Google,

TIP: Since we need to initialize some data, we use NSMutableDictionary. Please Google the difference between NSDictionary and NSMutableDictionary

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
id objc = nil;
[dict setObject:objc forKey:@"objc"];
Copy the code

This code translates into frida’s JS implementation as follows:

	var param_dict = ObjC.classes.NSMutableDictionary.alloc().init();
	param_dict.setObject_forKey_(body,"body");
Copy the code

The NSArray? Continue to Google

 NSArray *arr3 = [NSArray arrayWithObjects:@"one",@"two",@1, nil];
Copy the code

Translate it again

var NSArray = ObjC.classes.NSArray;
var param_Key_Array = NSArray.arrayWithObjects_(sBody,sClient,sClientVersion,sFunctionId,sOpenudid);
Copy the code

Unfortunately, this line of code won’t get through, and neither will Google. Go to Github with the beard

If you have a frida problem, don’t worry. Check Out Github with The Beard. You might be surprised.

I’m not alone, I have a lot of friends, the problem is the same, big beard says you need to add nil at the end of the argument

But how to add nil is a problem. Search # nils # again, a colleague offers a way to do it.

var NSArray = ObjC.classes.NSArray;
var nil = ObjC.Object(ptr("0x0"));
var param_Key_Array = NSArray.arrayWithObjects_(sBody,sClient,sClientVersion,sFunctionId,sOpenudid,nil);
Copy the code

The results are still not ideal, ran here still stuck.

Let’s go another way. Let’s try NSMutableArray

var param_Key_Array = ObjC.classes.NSMutableArray.arrayWithObject_(sBody);
param_Key_Array.addObject_(sClient);
param_Key_Array.addObject_(sClientVersion);
param_Key_Array.addObject_(sFunctionId);
param_Key_Array.addObject_(sOpenudid);
Copy the code

That’s great. That’s how it works

ObjectC class method call

GetSignWithDic is a class method, the called method is simple, the name behind add a underline can call, ObjC. Classes. XXSignService. GetSignWithDic_ (XXX).

Can getSignWithDic (a1,a2) take two arguments?

A multi-parameter call looks like this:

var signRc = ObjC.classes.XXSignService.getSignWithDic_keys_(param_dict,param_Key_Array);
Copy the code

Try it all out

function callSignFun(body,client,clientVersion,functionId,openudid){
	var param_dict = ObjC.classes.NSMutableDictionary.alloc().init();
	param_dict.setObject_forKey_(body,"body");
	param_dict.setObject_forKey_(client,"client");
	param_dict.setObject_forKey_(clientVersion,"clientVersion");
	param_dict.setObject_forKey_(functionId,"functionId");
	param_dict.setObject_forKey_(openudid,"openudid");

	// console.log("==== 1");
	var NSString = ObjC.classes.NSString;
	var sBody = NSString.stringWithString_('body');	
	var sClient = NSString.stringWithString_('client');	
	var sClientVersion= NSString.stringWithString_('clientVersion');	
	var sFunctionId = NSString.stringWithString_('functionId');	
	var sOpenudid = NSString.stringWithString_('openudid');
	
	var param_Key_Array = ObjC.classes.NSMutableArray.arrayWithObject_(sBody);
    param_Key_Array.addObject_(sClient);
    param_Key_Array.addObject_(sClientVersion);
    param_Key_Array.addObject_(sFunctionId);
    param_Key_Array.addObject_(sOpenudid);
	
	
	// console.log("==== 2");
	var signRc = ObjC.classes.XXSignService.getSignWithDic_keys_(param_dict,param_Key_Array);
	return signRc.toString();	
}

Copy the code

The result is there, as for whether it is right, I leave it to you to verify.

Third, summary

Timely saving is a good habit.

Forward programming experience is of great help in reverse work.

Frida is an artifact. ORZ.

The first thing we grow old is not our looks, but our dreams.

TIP: The purpose of this article is only one is learning more backward techniques and train of thought, if anyone use this technology to get illegal commercial interests the legal liabilities are their operators, and the author and it doesn’t matter, this paper involves the knowledge of code project can go to my friends to fly star come undone, welcome to join star learn together to explore technology knowledge. Have a problem can add me WX: FENfei331 discussion.

Wechat public account: Fenfei safety, the latest technology dry goods real-time push