乐趣区

关于ios:IOS-某电商App签名算法解析二-Frida-RPC调用

一、指标

Android 下用 frida 来做 rpc 调用计算签名,咱们曾经玩的很纯熟了。

明天介绍在 IOS 下的玩法。要点如下:

  • 参数类型确认
  • NSDictionary NSArray 等 ObjectC 对象的结构和复制
  • ObjectC 类办法和对象办法的调用
  • 附送福利,ObjectC 的 nil 参数如何结构

二、步骤

参考 Android 下的玩法

参照 [某段子 App 协定剖析 ( 三)] 咱们把 frida RPC 的框架先搭一下,这块的套路是一样的,

  • Flask 启动一个 web 服务
  • 脚本裸露一个接口进去给 Python 调用
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

处于演示目标,咱们这里创立一个 GET 接口,参数写死。理论利用的时候能够创立个 POST 接口,把参数传进来。

rpc.exports = {callsign : callSignFun};

脚本外面裸露一个 callsign 函数供 Python 调用。

参数类型确认

上篇文章中咱们曾经定位到了 +[XXSignService getSignWithDic:keys:],他有两个参数,只须要在 IDA 中 查看下这个函数被谁调用了,就能够看到入参的类型了。查看穿插援用还是上次教的 X 大法

关上 IDA, 一脸懵逼,昨天忘保留了,昨天忘保留了,忘保留了 ……

你知不知道昨天 IDA 嚼了一上午才搞定。难道还要来嚼一上午???

换个玩法吧,反正咱们曾经定位了,用 Frida 打印下参数类型试试。

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);

},

我就晓得 frida 不会让咱们悲观

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

参数 1 的类型是 NSDictionary,参数 2 是个字符串数组 NSArray

结构 NSDictionary 和 NSArray

毕竟咱们没搞过 ObjectC,只好面向谷哥编程了,

TIP: 因为咱们要初始化一些数据,所以这里应用 NSMutableDictionary 来实现,至于 NSDictionary 和 NSMutableDictionary 的区别,请自行谷歌

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

这段代码翻译成 frida 的 js 实现如下:

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

那 NSArray 呢?持续谷哥

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

再翻译一把

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

悲催的是,这行代码跑不过来,这下谷哥也不灵了,去大胡子的 github 看看

TIP: 遇到 frida 的问题,不要焦急,去大胡子的 github 搜搜,可能有惊喜。

吾道不孤,同道还是比拟多的,遇到的问题也一样,大胡子说你要在参数结尾加个 nil

然而这个 nil 怎么加也是个问题呀。再搜搜 #nil#,有个同道提供了一个办法,搞起来。

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

后果还是不现实,跑到这里还是卡死了。

换条路吧。咱们试试 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);

太棒了,这么搞能实现

ObjectC 类办法的调用

getSignWithDic 是一个类办法,类办法的调用很简略, 名称前面加个下划线就能够调用了,ObjC.classes.XXSignService.getSignWithDic_(xxx) 就能够了。

不简略的是,getSignWithDic 有两个参数,间接 getSignWithDic_(a1,a2) 能不能行?

年轻人,太 Native 了。多参数的调用是这样的:

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

残缺的搞一下

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();}

后果是有了,至于对不对,就留给大家去验证吧。

三、总结

及时保留是个好习惯。

正向编程教训对逆向工作有很大的帮忙。

Frida 是神器。ORZ。

咱们最先苍老的不是相貌,是幻想。

TIP: 本文的目标只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者本人承当,和本文以及作者没关系,本文波及到的代码我的项目能够去 奋飞的敌人们 常识星球自取,欢送退出常识星球一起学习探讨技术。有问题能够加我 wx: fenfei331 探讨下。

关注微信公众号: 奋飞平安 ,最新技术干货实时推送

退出移动版