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('\n 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中函數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM