zoukankan      html  css  js  c++  java
  • android逆向奇技淫巧二十四:frida rpc调用生成加密字段(九)

      1、上次自己构造了一个app来调用x音的关键so,结果在一条“LDR  R0, [R4,#0xC] “语句卡住了:通过ida查看得知:R4就是第三个参数,这里被当成了地址使用(java层怪不得用long类型)!第三个参数我是用frida hook得到的,换了个环境地址肯定也变了,所以这里直接”抄袭“拿过来用肯定报错,这种反调试的方法实在是秒啊!动态调试暂时卡壳,我们先来静态分析一下卡住语句的上下游:

    .text:000139A4 000 F0 B5                       PUSH            {R4-R7,LR}
    .text:000139A6 014 03 AF                       ADD             R7, SP, #0xC
    .text:000139A8 014 2D E9 00 0F                 PUSH.W          {R8-R11}
    .text:000139AC 024 93 B0                       SUB             SP, SP, #0x4C
    .text:000139AE 070 CD E9 03 23                 STRD.W          R2, R3, [SP,#0x68+var_5C]
    .text:000139B2 070 05 46                       MOV             R5, R0
    .text:000139B4 070 3A 48                       LDR             R0, =(__stack_chk_guard_ptr - 0x139BC)
    .text:000139B6 070 0C 46                       MOV             R4, R1
    .text:000139B8 070 78 44                       ADD             R0, PC  ; __stack_chk_guard_ptr
    .text:000139BA 070 00 68                       LDR             R0, [R0] ; __stack_chk_guard
    .text:000139BC 070 01 90                       STR             R0, [SP,#0x68+var_64]
    .text:000139BE 070 00 68                       LDR             R0, [R0]
    .text:000139C0 070 38 49                       LDR             R1, =(unk_99110 - 0x139CA)
    .text:000139C2 070 12 90                       STR             R0, [SP,#0x68+var_20]
    .text:000139C4 070 E0 68                       LDR             R0, [R4,#0xC] ; 自己构造的app在R4的值是第3个long参数,地址无效
    .text:000139C6 070 79 44                       ADD             R1, PC  ; unk_99110
    .text:000139C8 070 10 90                       STR             R0, [SP,#0x68+var_28]
    .text:000139CA 070 08 31                       ADDS            R1, #8
    .text:000139CC 070 04 30                       ADDS            R0, #4  ; rwlock
    .text:000139CE 070 0F 91                       STR             R1, [SP,#0x68+var_2C]
    .text:000139D0 070 F3 F7 36 EF                 BLX             pthread_rwlock_rdlock
    .text:000139D4 070 11 90                       STR             R0, [SP,#0x68+var_24]

      卡住的语句后面做了注释:从R4+C的地方取4字节数据存入R0,然后把R0存到栈上;接着把R0+4,这里ida已经识别出了是rwlock读写锁,然后就是调用pthread_rwlock_rdlock获取读写锁的读锁!这就很关键了:

      (1)为什么要对数据加读锁了而不是互斥锁了?在互斥机制中,读者和写者都需要独立独占互斥量以独占共享资源;而在读写锁机制下,允许同时有多个读者读访问共享资源,只有写者才需要独占资源。相比互斥机制,读写机制由于允许多个读者同时读访问共享资源,进一步提高了多线程的并发度。这里我个人猜测:加密字段输入了长长的url+http头的很多字段,需要输出4个加密字段,如果让单线程顺序读取并计算,效率很低,影响用户体验,所以使用多线程机制协同:多个线程同时读取输入,分别计算不同的加密字段

          (2)从ida的trace记录看,前面所有的指令都没有读取栈上保存的url+http头的数据,所以前面肯定还没来得及生成那4个加密字段;从这里开始用读写锁,结合上面的分析大胆猜测:接下来要开始生成加密字段了!换个角度,这个函数附近有好些地方都调用pThread_Create函数,从这里开始计算机密字段嫌疑很大!

      2、既然卡在了第三个地址参数,自然需要分析一下这个参数的来源,直接上frida,先hook h.a方法,看看这个函数在java层的调用路径:

          at ms.bd.c.h.a(Native Method)
            at ms.bd.c.b.a()
            at ms.bd.c.u1$a.a(:34013379)

          发现是u1$a.a在调用,在jadx静态分析u1$a.a这个方法,发现是

    String[] strArr = (String[]) C85964b.m218696a(50331649, 0, C86039u1.this.f357108d, str, (String[]) arrayList.toArray(new String[0]));  这行代码调用了b.a方法,里面涉及到了long参数(已经标黄),而这个long参数是u1类的成员变量,在u1.a方法被设置了,这个函数的参数只有1个long类型,继续hook这个方法:调用栈如下:

     [Android Emulator 5554::com.ss.android.ugc.aweme]-> 3069366032
        java.lang.Throwable
            at ms.bd.c.u1.a(Native Method)
            at ms.bd.c.t1.a()
            at ms.bd.c.b$a.a()
            at ms.bd.c.b.b()
            at ms.bd.c.h.b()
            at ms.bd.c.h.a(Native Method)
            at ms.bd.c.b.a(:33882150)
            at ms.bd.c.m1.a()
            at com.bytedance.mobsec.metasec.ml.c.a()
            at com.ss.android.ugc.aweme.sec.SecApiImpl.initSec(SecApiImpl.kt:117965016)
            at com.ss.android.ugc.aweme.net.t$g.c(NetworkInitTask.kt:17170615)

       神奇地发现:居然还是h.a在调用,形成环形了,唯一的解释:h.a参数不同,生成的结果就不同!之前hook h.a的时候确实也发现了其他参数,但当时目的是追踪这4个加密字段,完全没重视其他参数。哎,悔不当初!

      接着追溯:上面调用栈中有一个方法是com.ss.android.ugc.aweme.sec.SecApiImpl.initSec,该方法部分代码如下(太多了,这里只贴一部分);

     public final void initSec(Context context, String str, int i, String str2, String str3, boolean z, SecGetDataCallBack dVar) {
            String str4;
            if (!PatchProxy.proxy(new Object[]{context, str, Integer.valueOf(i), str2, str3, Byte.valueOf(z ? (byte) 1 : 0), dVar}, this, changeQuickRedirect, false, 338895).isSupported) {
                C51302a.m136764a(4, "Sec", "initSec");
                if (!PatchProxy.proxy(new Object[]{context, str, Integer.valueOf(i), str2, str3, Byte.valueOf((byte) z), dVar}, null, DmtSec.f284302a, true, 338875).isSupported) {
                    DmtSec.f284308g = new SecInitReceiver(DmtSec.C66800a.f284321b);
                    IntentFilter intentFilter = new IntentFilter();
                    intentFilter.addAction("com.ms.init");
                    DmtSec.m171500a(context, DmtSec.f284308g, intentFilter);
                    SecLogger bVar = SecLogger.f284353b;
                    bVar.mo193744a(SecLogger.f284354c, "init language = " + str + ", aid = " + i + ", appName = " + str2 + ", channel= " + str3);
                    long currentTimeMillis = System.currentTimeMillis();
                    long currentTimeMillis2 = System.currentTimeMillis();
                    GlobalContext.setContext(context);
                    C30329a.C30330a aVar = new C30329a.C30330a(String.valueOf(i), "bo95dJizD1WFcV03zOuLzN5Pn1sFtVa3szqiVQmflMJTNW0p0Kpqfw8D4i0zUlfrou4kuYt/i0521YRygM83dwv/wn3DD+TMJF+QFzW9wb8Qq2/1B4jPMbObrDNdyMMukpAYqy1fLWtbLGVIPxsFsZegwQy5lsRX9h49PH/Qx8MwgYvWvH7ZTFLV28LwTWZiljQyBPaBE+TsyumEu0Y+JRkeidHFEYcVs0yRoa+xC004hugQhdPupIt6dBiWA4phsB3fNJZjFTAKGE1lPB4gzt6Qf+FmlgZBbRvT8zekxTV2HZ5dUvSutB2/0QpbHKAvWL4DRA==");
                    aVar.mo248346a(0);
                    aVar.mo248347a("tk_key", "douyin");

       代码里面有写死的字符串,比如tk_key、douyin,还有很长的base64编码的bo95dJizD1WFcV03zOuLzN5Pn1sFtVa3sz....,刚好在hook h.a方法的时候,有一组参数是这样的:

    enter=============ms.bd.c.h.a=======================================================
    arg[0]:67108865
    arg[1]:0
    arg[2]:0
    arg[3]:["1128","","","bo95dJizD1WFcV03zOuLzN5Pn1sFtVa3szqiVQmflMJTNW0p0Kpqfw8D4i0zUlfrou4kuYt/i0521YRygM83dwv/wn3DD+TMJF+QFzW9wb8Qq2/1B4jPMbObrDNdyMMukpAYqy1fLWtbLGVIPxsFsZegwQy5lsRX9h49PH/Qx8MwgYvWvH7ZTFLV28LwTWZiljQyBPaBE+TsyumEu0Y+JRkeidHFEYcVs0yRoa+xC004hugQhdPupIt6dBiWA4phsB3fNJZjFTAKGE1lPB4gzt6Qf+FmlgZBbRvT8zekxTV2HZ5dUvSutB2/0QpbHKAvWL4DRA==","","","","","","0","-1",[],["tk_key","douyin"]]
    arg[4]:null
    java.lang.Throwable
        at ms.bd.c.h.a(Native Method)
        at ms.bd.c.b.a(:33882150)
        at ms.bd.c.m1.a()
        at com.bytedance.mobsec.metasec.ml.c.a()
        at com.ss.android.ugc.aweme.sec.SecApiImpl.initSec(SecApiImpl.kt:117965016)
        at com.ss.android.ugc.aweme.net.t$g.c(NetworkInitTask.kt:17170615)

      猜测args[3]就是在initSec这里拼凑出来的!回到u1.a方法的调用栈,分析这个栈的思路:一层一层网上追溯,看看到底是哪个地方改变了long参数的值,根据一些magic number,找到了

    ms.bd.c.ml.a()函数,这个函数刚好有同样的magic number,并且也在调用栈上!从代码看,这个函数调用了b.a,然后b.a调用了h.a,也符合调用栈的回溯,而且调用的b.a的返回值下面也被强制转成了long类型,所以这里实锤了就是ms.bd.c.ml.a()生成了long参数!

             

            ms.bd.c.ml.a()调用ms.bd.c.b.a(67108866,str)函数生成了a,a被强制转成了long类型,所以这里重点关注ms.bd.c.b.a(67108866,str)这个函数;由于还有str参数不知道是啥,我们自己调用的时候也不知道怎么传参,所以这里继续hook ms.bd.c.b.a函数,看看传入了什么参数,如下:

    enter=============ms.bd.c.b.a==========================
    arg[0]:67108866
    arg[1]:1128
    java.lang.Throwable
            at ms.bd.c.b.a(Native Method)
            at ms.bd.c.m1.a()
            at com.bytedance.mobsec.metasec.ml.c.a()
            at com.ss.android.ugc.aweme.sec.SecApiImpl.initSec(SecApiImpl.kt:117965023)
            at com.ss.android.ugc.aweme.sec.SecApiImpl.initSec(Native Method)
            at com.ss.android.ugc.aweme.net.t$g.c(NetworkInitTask.kt:17170615)
            at com.bytedance.ies.ugc.aweme.network.f.a(Network.kt:34013540)
            at com.bytedance.ies.ugc.aweme.network.f$a.call(Network.kt:262169)
            at bolts.Task$10.run(Task.java:262180)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
            at com.ss.android.ugc.aweme.bp.d$3$1.run(NewInstanceFactory.java:262193)
            at java.lang.Thread.run(Thread.java:761)

    ms.bd.c.b.a retval:-1500374080
     leave=============ms.bd.c.b.a==========================

      发现另一个参数是1128,返回是-1500374080=0xFFFFFFFFA6921BC0,看着确实像个地址;数值上和hook u1.a时看着差异较大,但我能确定就是这个函数生成了long参数,原因:

         (1)数值不等可能是js不制obj直接转成long导致的,需要想办法转换类型

         (2)从ms.bd.c.ml.a()函数的代码分析,调用ms.bd.c.b.a的返回的值被转成了long使用!

         (3)从frida打印函数调用的顺序看,打印了ms.bd.c.u1.a后立即打印ms.bd.c.h.a,说明这两个存在调用关系

      既然确认ms.bd.c.b.a返回了long,这里马上用自己的app调用ms.bd.c.b.a(67108866,"1128")试试,结果如下:函数的返回值居然是null!

           

       这里出乎意料,我hook x音app时明明有返回的呀,并不是null!又出啥问题了? 不过这次有明显的改善:自己写的app至少没崩,说明参数设置是没任何问题的,个人猜测是metasec_ml内部可能有些检测机制,发现是第三方调用就返回null!

       为了查明原因,继续用ida调试,诡异的现象发生了:F7单步调试的时候遇到跳转的地址有问题,报错!

      

          不能就这样算了啊,调式都不行了,怎么排查了?继续用ida trace,这次在同样的地方居然不报错了(F8步过也不报错,就特么F7步入报错),trace的时候遇到了和用unidbg类似的问题,总式因为mutex卡在死循环这里鬼打墙:实在没办法了,把0x72C8E这4个字节NOP掉,不让上锁!

       

       trace又能顺利执行了!从trace的结果看:R0和R1分别从两个地方取值,然后相减得到的结果保存到R0,也就是返回值,这里是0,怪不得67108866=0x4000002和1128这组参数返回的是null;

    00003667    libmetasec_ml.so:F31D0514    LDR             R0, [SP,#0xC]       R0=0A423869                                 
    00003667    libmetasec_ml.so:F31D0516    LDR             R1, [R5]            R1=0A423869                                 
    00003667    libmetasec_ml.so:F31D0518    SUBS            R0, R1, R0          R0=00000000 Z=1 N=0             

      由于不知道原app是怎么跑的(感兴趣的小伙伴也可以用frida stalker trace原app),这里我也没法继续分析R0和R1俩个值为啥相等(因为没有原app trace的对比,我也不知道自己代码执行的路径中哪个分支走错了)!回到我们自己构造的app卡住的代码,如下:

       R4就是h.a传入的第三个long函数,这里是个地址,加上0xC后取出值存放在R0,然后又存放在栈上,最后+4后得到rwlock传入pthread_rwlock_rdlock,那么问题来了:原app中b.a(0x4000002,"1128")得到的是R4的地址,又经过一系列算式得到rwlock,为啥我们不自己构造一个rwlock,然后把地址传给R4了?自己从写写个so,里面生成pthread_rwlock_t对象,然后调用pthread_rwlock_init初始化,把对象的地址保存;由于原app中涉及到R4+0xC和R0+4等“偏移”,所以我在c代码里用了结构体;为了便于查找,给rwlock周围的变量复制了0x11111111、0x22222222等数值,结果如下:

          

       从ida调试的结果看,原来卡住的“LDR R0, [R4,#0xC]”的这样代码现在能正常执行了!R0确实指向了rwlock(从内存的值看,调用pthread_rwlock_init初始化后还是0,那初始化还有啥用了?)

             

            继续往下走,又遇到问题:R1明显是我自己构造magic number,这里被当成地址来用了,说明我当初构造的rwlock结构体前面的数值应该是个地址!这里的偏移0xF357465A-0xF3569000=0xb65a;

           

       往上追溯,这里的R1来自R4+4,这里也刚过上一个卡点;

            

        既然找到原因了,继续补呗!在自己的结构体把原来的0x22222222换成地址(注意:根据单步调试自己写的app分析,这里一共有4层指针引用,每层都要自己写指针嵌套引用);补上后继续调试,特么又遇到同样的问题(如下):还是地址为0,只不过换了个地方,说明构造的地址已经通过了上次代码的执行;

        

       往上追溯调试:偏移为0xB8C0的地方,此时R1就是我自己构造的p4指针,但是这里很鸡贼地取了p4+8作为地址,而我并没有构造p4+8,所以内存是0(p4我构造的是0x77777777);这里的p1到p4是我自定义的指针,层层递进引用(建议下载末尾的源码查看具体的定义和调用)!

            

       继续漫漫追溯,发现这里的push把寄存器的值压栈上了,这里的偏移:0x6D970

            

       发现R1和R2还是从栈上取得!这里得偏移:0x13A14

          

          发现是之前R1和R2存栈上得!偏移:0xB8C0,又回到了p4+8的地方!

           

       继续用结构体去补:貌似补上了!

           

           又发现一个地方:0xBE4C;还好自己填的值辨识度高,这里一眼就看出了是那个字段的赋值有问题!继续补上!

       

         继续往下:发现我们自己填的0x22222222被当成跳转的代码地址了,呵呵......    偏移:13A42

         

       由于是跳转到新地址,此时我也不知道应该补什么地址,只能继续查看原app的跳转地址。这里可以用frida hook,看看context;也可以直接用ida调试原app;我直接用ida,简单方便,查到了这里跳转的地址:偏移是0x14581

            

       来到0x14581这里,发现还有大量的计算逻辑:原本是想把上面的BLX R6直接NOP掉,但是看到还有这么多代码,担心逻辑出错,想想还是算了;只能想办法得到metasec的基址,再加上0x14581的偏移来替代我之前设置的0x22222222,来保证原有的逻辑正常!

      

           至此,so层所有的逻辑都补全了,h.a可以顺利运行完毕,没有任何,但结果却是返回0!和上面调用ms.bd.c.b.a(67108866,“1128”)得到long的结果是一样的!x音原来的app是可以正常运行的,hook的结果也是对的,但自己补全了参数得到的结果是0,直接传参调用的结果还是0,说明:(1) h.a还有其他的反调试或检测逻辑:一旦发现so被第三方调用了,直接返回0!(2)我自己补的参数可能有问题导致代码运行的逻辑出错!文章末尾是我自己构建的app,哪位能提示甚至帮忙把第三个参数构造好,站内私信我加微信发红包!

        直接来硬的不行那就继续绕呗!有两种思路:

    •  x音原app调用ms.bd.c.b.a(67108866,“1128”)生成了第三个long参数,为啥我不能调用了?
    •    x音原app调用ms.bd.c.b.a生成那4个加密字段,为啥我不能调用了?唯一不确定的就是第三个long参数,直接hook原app得到后再“为我所用”呗!

      自己构造app是为了反调试和主动调用,用frida rpc一样可以的嘛!为了直接用rpc执行ms.bd.c.b.a,这里彻底地做一次伸手党:先hook ms.bd.c.b.a得到第三个long参数,保存后再通过rpc主动执行ms.bd.c.b.a生成加密字段!rpc代码如下:

          call.js文件:

    function printStringArry(strArr){
        var FastJson = Java.use('com.alibaba.fastjson.JSON'); 
        return FastJson.toJSONString(strArr);
    }
    
    function convert2ArrayList(str){
        var ArrayList = Java.use('java.util.ArrayList').$new();
        var strObj = Java.use('java.lang.String').$new();
        var strArray = new Array();
        strArray = str.split(",");
        for(var i=0;i<strArray.length;i++){
            ArrayList.add(strArray[i]);
        }
        return ArrayList;
    }
    
    var longParam;
    function getLongParam(){
        Java.perform(function(){
            var h_class = Java.use("ms.bd.c.h");
            h_class.a.overload('int', 'int', 'long', 'java.lang.String', 'java.lang.Object').implementation = function(){
                if(arguments[2]!=0){
                    longParam = arguments[2];
                    console.log('
     longParam = arguments[2]:' + longParam);
                }
                return this.a(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]);
            }
        });
    }
    
    function ms_bd_c_h_a(args0,args1,args2,args3,args4){
        var encrypt_result;
        Java.perform(function() {
            args2 = longParam;
            args4 = convert2ArrayList(args4.toString());
            try{
                var targetClass = Java.use("ms.bd.c.h");
                encrypt_result = targetClass.a(args0,args1,args2,args3,args4);
            }catch(e){
                console.log(e.stack);
            }
            console.log("encrypt_result is :"+printStringArry(encrypt_result));
        });
        return encrypt_result;
    }
    
    setImmediate(getLongParam);
    
    rpc.exports =  {
        encrypt: ms_bd_c_h_a
    };

      python文件:注意,args4是post数据包的head,需要改成和url匹配的head,否则app会崩掉!

    # -*- coding, utf-8 -*-
    import codecs
    import frida
    import time
    
    session = frida.get_usb_device().attach('抖音')
    
    #读取JS脚本
    with codecs.open('./call.js', 'r', 'utf-8') as f:
        source = f.read()
    
    script = session.create_script(source)
    script.load()
    
    rpc = script.exports
    
    time.sleep(5)#给hook预留时间,让x音触发ms.bd.c.h.a函数;期间也可以手动点赞、滑动屏幕等方式触发ms.bd.c.h.a函数
    
    args0 = 50331649
    args1 = 0
    args2 = 0
    args3 = "https,//aweme.snssdk.com/aweme/v1/commit/item/digg/?aweme_id=7016928444202175783&type=0&channel_id=0&city=510100&activity=0&os_api=25&device_type=SM-G9750&ssmix=a&manifest_version_code=150501&dpi=280&app_name=aweme&version_name=15.5.0&ts=1633766716&cpu_support64=false&app_type=normal&ac=wifi&appTheme=light&host_abi=armeabi-v7a&channel=lephone_xh_sd_1128_0415&update_version_code=15509900&_rticket=1633766717162&device_platform=android&iid=2401771765105502&version_code=150500&cdid=5b43e48d-b149-4c8a-8863-b2d84e650be4&openudid=b83ec6a675adba6a&device_id=4380918606995591&resolution=1080*1920&device_brand=samsung&language=zh&os_version=7.1.2&aid=1128&minor_status=0&mcc_mnc=46000"
    args4 = ["accept-encoding","gzip","cookie","n_mh=B6WRe0yd-1qIuffF6ZWNO-CSGlW1Q-VhC0E79NrqYTg;uid_tt=b21518a30e097fbd558cdddf9bcfd3a5;uid_tt_ss=b21518a30e097fbd558cdddf9bcfd3a5;sid_tt=5a51412bfb955ee582edae8d48765690;sessionid=5a51412bfb955ee582edae8d48765690;sessionid_ss=5a51412bfb955ee582edae8d48765690;d_ticket=6b7d0d3678f21faa482196c460483d4eed15d;install_id=2542488099492919;ttreq=1$a01a1173c36665a50314924786f4704df6cdeb45;sid_guard=5a51412bfb955ee582edae8d48765690%7C1633073022%7C5184000%7CTue%2C+30-Nov-2021+07%3A23%3A42+GMT;odin_tt=0ea847f78343f7e969e78ba7b9239200535f7a60e9667c1a9bd3eff221ae71e00ec61567785d8a107011c961fae3961c835c25f4bfd09dec3446bd650115e45263f7c216cd7d33846418d3b45f505996","passport-sdk-version","18","sdk-version","2","x-ss-req-ticket","1633766717163","x-tt-dt","AAA3VJFIKPXTQ3DZW622UN5YMCIJ3AQ5BZMAI2TMBJQASG3PQIMUKVBQYQG2YCXGALRNNZBQUJ7XDNZ4FXIGI2TL5LI5XLUXSPCTZ4NJGDU4JCIL2UF6OEV25GKGINMX7ARAHHRP5IU6VITY2YJ4BCI","x-tt-token","005a51412bfb955ee582edae8d48765690009b144562dfd76dacbe19854da5bd41e9bc9c249278cf5cfd759602ab0bab22f34d19554661df3791190f9068394dd1e6f7edd268b7fa3c5a0b745f1aee15931aa0b0f43260e7297fb7d16d872614ca256-1.0.1"]
    result = rpc.encrypt(args0,args1,args2,args3,args4)
    print("five gods,",result)
    
    session.detach()

      在写rpc调用时遇到的几个坑在这里分享一下,希望对大家有所帮助:

    •   这里涉及到3中不同的语言:java、js、python,每种语言的类型是不一样的;java层ms.bd.c.b.a的参数是('int', 'int', 'long', 'java.lang.String', 'java.lang.Object'),但是js是弱类型,并没有long类型;python同理也没有,该怎么构造long参数了?我这里是直接在js里面hook ms.bd.c.b.a后保存了第三个参数,然后传入rpc调用;如果通过python传进来,可以用int(data)转换,在js统一识别成number类型;我想过用Java.cast、Java.use('java.lang.Long').parseLong.overload('java.lang.String').call(Java.use('java.lang.Long'), args2)等方式强转成long,但都没卵用!
    •    最后一个参数类型是java.lang.Object,如果直接把key/value字符串转成string传进去,app会直接崩掉(如果x音是故意这么干的,说明反调试做的牛逼;如果不是,说明鲁棒性没考虑周全,没有对错误的参数做处理);如果直接传入["accept-encoding":"gzip","cookie":"n_mh=B6WRe0yd-".....] 这种list类型会爆下面的错误,说明python的list根本不匹配java.lang.Object
      Error: a(): argument types do not match any of:
         .overload('int', 'int', 'long', 'java.lang.String', 'java.lang.Object')
      最后从下面ms.bd.c.u1$a.a调用的代码看,传入的是string[]数组,所以需要构造string[]数组才行!看x音原app是先放入ArrayList,我在js代码里面就照做了!
         ms.bd.c.u1$a.a方法代码:String[] strArr = (String[]) C85964b.m218696a(50331649, 0, C86039u1.this.f357108d, str, (String[]) arrayList.toArray(new String[0])); 这里明显直接调用了ms.bd.c.b.a方法,连第三个long参数都直接用了,不需要自己幸苦生成;用户只需要传入url和post包的head参数即可,更加省事,感兴趣的小伙伴建议自行尝试rpc调用这个函数试试!
    public final Map<String, String> mo70417a(String str, Map<String, List<String>> map) {
                String str2;
                PatchProxyResult proxy = PatchProxy.proxy(new Object[]{str, map}, this, f357109a, false, 431597);
                if (proxy.isSupported) {
                    return (Map) proxy.result;
                }
                HashMap hashMap = new HashMap();
                if (!(str == null || map == null)) {
                    if (str.toLowerCase().contains((String) C85985h.m218727a(16777217, 0, 0, "2412bc", new byte[]{43, 34, 86, 86})) || str.toLowerCase().contains((String) C85985h.m218727a(16777217, 0, 0, "fd1c18", new byte[]{Byte.MAX_VALUE, 114, 86, 7, 29}))) {
                        C86055z1.m218845a().mo248383b();
                        ArrayList arrayList = new ArrayList();
                        for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                            String key = entry.getKey();
                            if (entry.getValue() == null || entry.getValue().size() <= 0) {
                                str2 = null;
                            } else {
                                str2 = entry.getValue().get(0);
                            }
                            if (!(key == null || str2 == null)) {
                                arrayList.add(key);
                                arrayList.add(str2);
                            }
                        }
                        String[] strArr = (String[]) C85964b.m218696a(50331649, 0, C86039u1.this.f357108d, str, (String[]) arrayList.toArray(new String[0]));
                        if (strArr != null) {
                            HashMap hashMap2 = new HashMap();
                            for (int i = 0; i < strArr.length; i += 2) {
                                hashMap2.put(strArr[i], strArr[i + 1]);
                            }
                            return hashMap2;
                        }
                    } else {
                        throw new RuntimeException((String) C85985h.m218727a(16777217, 0, 0, "3ff0e1", new byte[]{43, 112, 85, 73, 79, 53, 36, 7, 53, 101, 98, 108, 1, 80, 74, 105, 56, 83, 35, 112, 49}));
                    }
                }
                return hashMap;
            }

       同时,在metasec_ml偏移0x13220处发现了重要的函数:第一个参数是url

          

       第二个参数是post包的head参数,so层0x13220的这个函数和java层的ms.bd.c.u1$a.a方法在参数上出奇一致,很有可能0x13220也参与了加密字段的生成,至少是提供了加密算法的原始数据

         

      自己构造app: 链接:https://pan.baidu.com/s/1JavGwlMKtcpnQkaVB2zmNw    提取码:3fd6    调用ms.bd.c.b.a时返回值是0,暂时还没生成加密字段,问题还在排查中;能帮忙解决问题的私信我加微信,我发红包!

    参考:

    1、https://blog.csdn.net/shaoyiju/article/details/53241808 读写锁的原理及用法

    2、https://blog.csdn.net/qq_30135181/article/details/108221043 调用so中函数

  • 相关阅读:
    leetcode 350. Intersection of Two Arrays II
    leetcode 278. First Bad Version
    leetcode 34. Find First and Last Position of Element in Sorted Array
    leetcode 54. Spiral Matrix
    leetcode 59. Spiral Matrix II
    leetcode 44. Wildcard Matching
    leetcode 10. Regular Expression Matching(正则表达式匹配)
    leetcode 174. Dungeon Game (地下城游戏)
    leetcode 36. Valid Sudoku
    Angular Elements
  • 原文地址:https://www.cnblogs.com/theseventhson/p/15366118.html
Copyright © 2011-2022 走看看