????新版D音由于插入了過(guò)多破壞性代碼淋叶,已經(jīng)無(wú)法由jadx反編譯成功了,太多地方都解析失敗等限。我嘗試用MT管理器換引擎反編譯爸吮,也都是一樣的結(jié)果芬膝。這里如果想分析,需要jadx結(jié)合smali代碼硬啃形娇。我對(duì)著smali啃了一個(gè)參數(shù)锰霜,有些蛋疼。桐早。于是還是用豌豆莢下了歷史版本癣缅,反編譯看java了。
抓包
? ? 首先還是登錄抓包:
? ? ? ?首先是post請(qǐng)求哄酝,有query、body陶衅、cookie和另外的一些字段屡立。換個(gè)手機(jī)號(hào)登錄再抓一次作對(duì)比门烂。參數(shù)太多乳愉,不方便看,切換到WebForms選項(xiàng)卡屯远,對(duì)比參數(shù)蔓姚,首先是query。第一次抓包:
? ? ? ? 第二次抓包:
? ? 可以看到變化的只有 ts 和 _rticket氓润,很容易看出來(lái)赂乐,一個(gè)是10位時(shí)間戳,一個(gè)是13位時(shí)間戳咖气。那么query方面可能沒(méi)有我們太需要關(guān)注的地方挨措。
? ? 然后body:
? ? 手機(jī)號(hào)與密碼經(jīng)過(guò)了加密。再看下其他內(nèi)容:
? ? X-Khronos與X-SS-REQ-TICKET依然是時(shí)間戳崩溪,這里需要注意的參數(shù)是X-Gorgon浅役、X-SS-STUB和x-tt-trace-id。對(duì)比兩次請(qǐng)求伶唯,我們發(fā)現(xiàn)x-tt-trace-id里中間有一部分與末尾部分是相同的觉既,猜測(cè)與cookie或是一些本地配置參數(shù)有關(guān)。cookie重新打開(kāi)了幾次,也沒(méi)有發(fā)生變化瞪讼,暫時(shí)也不看钧椰。這個(gè)cookie的生成盲猜要比登錄協(xié)議復(fù)雜得多。
? ? 那么確定下來(lái)需要找的參數(shù):body中的password符欠、mobile嫡霞、header中的X-Gorgon、X-SS-STUB和x-tt-trace-id希柿。
分析
? ? 還是慣例诊沪,jadx全局先搜一波url唄。?
? ? 很容易的就找到這里曾撤《艘Γ可以看到在將手機(jī)號(hào)與密碼put進(jìn)map之前,執(zhí)行了StringUtils.encryptWithXor函數(shù):
? ? 比較簡(jiǎn)單挤悉,先轉(zhuǎn)成bytes數(shù)組渐裸,逐位與5進(jìn)行亦或,最后再轉(zhuǎn)成16進(jìn)制拼接為字符串装悲。驗(yàn)證一下:
? ? 相同橄仆。密碼同樣。
? ? 然后分析header中的字段衅斩。搜索X-Gorgon,找到這個(gè)類(lèi):
? ? 一個(gè)匿名類(lèi)怠褐,我們hook一下a方法畏梆。這里夜神模擬器的firda又出問(wèn)題了,換真機(jī)測(cè)試奈懒。奠涌。hook腳本與輸入結(jié)果如下:
? ? 第一個(gè)參數(shù)str也就是完整的url,第二個(gè)參數(shù)map就是所有其他的headers參數(shù)磷杏,包括cookie溜畅、x-ss-req-ticket、user-agent极祸、accept等參數(shù)慈格。同時(shí)x-tt-trace-id與X-SS-STUB在此之前就已經(jīng)賦值:
? ? 回到代碼分析,我們找到X-Gorgon的來(lái)源:a3遥金,a3是通過(guò)調(diào)用上面的函數(shù)得到的浴捆。
? ? 大概要找出來(lái)的參數(shù)有:i,a2稿械,str4选泻,str5,str6,那個(gè)currentTimeMillis是10位int類(lèi)型的時(shí)間戳页眯。
? ? 我們先hook最后的a.a方法梯捕,看看a2、str4窝撵、str5傀顾、str6是什么:
? ? 幾乎沒(méi)任何參考價(jià)值。忿族。還是一步一步看锣笨。
? ? a2:
? ? ? ? 由d.a(b2)得到,b2由tt.d(str)得到道批,str是url错英。看看tt.d做了什么:
? ? ? ? 對(duì)url進(jìn)行了切割隆豹,獲取?到#的部分椭岩,也就是query部分。再看d.a():
? ? ? ? 對(duì)query部分進(jìn)行md5璃赡,解決一個(gè)判哥。
? ? str4:從Map中取X-SS-STUB,如果有則賦值碉考,否則賦為32個(gè)0塌计;
? ? ? str5和str6都在這里:
首先是str5,對(duì)cookie進(jìn)行md5侯谁。str6對(duì)cookie先調(diào)了tt.e():
? ? 就是從cookie里取sessionid锌仅,然后再md5。以上4個(gè)參數(shù)如果為空墙贱,就賦32個(gè)0热芹。最后是a.a:
? ? 各種位運(yùn)算。懶得看了惨撇。接下來(lái)分析i:
? ? 如果map中有“META-SHADOWMAZE”則為1伊脓,否則為-1。
? ? 然后是一個(gè)巨長(zhǎng)無(wú)比的調(diào)用鏈:
? ? 最外層的a:
? ? 以及發(fā)現(xiàn)驚喜的leviathan魁衙,native报腔!驚不驚喜意不意外!不往下看了??纺棺!
? ? 上面還漏了兩個(gè)大坑:x-tt-trace-id與X-SS-STUB榄笙。
? ? 全局搜索X-SS-STUB,定位到下面:
? ? 跟進(jìn):
? ? 接口+抽象方法〉或颍現(xiàn)在我們掌握的線索有茅撞,真實(shí)調(diào)用的類(lèi)一定繼承自TypedOutput,并且實(shí)現(xiàn)了md5Stub()方法。全局搜索String md5Stub():
? 這里就不太好看了米丘,嘗試用frida打印調(diào)用棧剑令,只要找到調(diào)用棧,我們不就知道到底走的哪條路線了嗎拄查。但是使用frida啟動(dòng)時(shí)遇到:
? 這是由于activity沒(méi)有指定被調(diào)用的Intent吁津,我在Manifest.xml中加入后依然報(bào)錯(cuò),遇到了知識(shí)盲區(qū)堕扶,暫時(shí)無(wú)法解決碍脏。那么換一個(gè)思路,可以選擇去hook每一個(gè)方法稍算,或者動(dòng)態(tài)調(diào)試典尾。對(duì)于自己來(lái)說(shuō)目前可能還是hook比較順手,而且這幾個(gè)方法也比較簡(jiǎn)單糊探,直接去hook就可以钾埂,看打印出哪個(gè)那就是了。最終確定科平,這里真實(shí)調(diào)用的是com.bytedance.retrofit2.mime.b類(lèi)中的md5Stub()褥紫。
? ? 查找md5Stub的用例卻沒(méi)有查找到。觀察b中沒(méi)有構(gòu)造方法瞪慧,其中的主要類(lèi)變量f31162a是在a方法中初始化:
? ? 追蹤a的調(diào)用髓考,一共有兩處,我們來(lái)到了這里:
? ? 繼續(xù)找調(diào)用它的地方弃酌。
? ? 有點(diǎn)眼熟啊绳军,貌似是從Map里取了一些參數(shù)。Map很有可能是query矢腻、body、或者h(yuǎn)eader中的某些部分射赛。再回去看上面負(fù)責(zé)初始化f31132a的a方法多柑,就是把傳過(guò)來(lái)的參數(shù)一一組合,以&和=做連接楣责。
? ? 既然我們已經(jīng)知道b類(lèi)中的md5Stub一定會(huì)被調(diào)用竣灌,而a又是初始化md5Stub中參數(shù)f311332a的唯一途徑,那么可以按照如上的思路秆麸,編寫(xiě)hook代碼初嘹,嘗試還原最終拼接后的參數(shù):? ??
? ? 這不就是post的請(qǐng)求體嗎?再回去看調(diào)用鏈:
? ? 先對(duì)上面的字符串取md5,再對(duì)結(jié)果執(zhí)行a方法:
? ? 又是一些位運(yùn)算沮趣,結(jié)果就是最終的X-SS-STUB屯烦。
總結(jié)
? ? java層還是屬于皮毛,真正難的地方在so層,D音so層加載Map足以讓人絕望驻龟。這次在找x-ss-stub的時(shí)候温眉,遲遲定位不到關(guān)鍵代碼,全局搜索不出來(lái)翁狐,方法剖析和打印調(diào)用棧都GG的情況下类溢,略有小懵。不過(guò)能用的方法還是太多了露懒,總有一款適合你闯冷。。懈词。
聲明
?????????聲明:本文分析過(guò)程僅供學(xué)習(xí)蛇耀,并無(wú)任何個(gè)人以及商業(yè)或其他用途。如有不慎侵權(quán)钦睡,請(qǐng)聯(lián)系我刪除蒂窒。