前言
使用開源工具出現(xiàn)問題而且很難在網(wǎng)上查找到解決方案的時候,最好的解決方法就是研究它的源碼,因為那樣能為我們提供更多的信息。
搭建調(diào)試環(huán)境
首先我們在github上拉取smali/baksmali的源碼
可以看出該項目采用了grade自動化構(gòu)建工具來編譯源碼的,因此我們可以在android studio中導(dǎo)入該項目,如下圖所示:



然后開始編譯baksmali,如下圖,雙擊fatjar即可,gradle會自動尋找缺失的模塊下載并編譯:

生成的baksmali在如下目錄下面:

然后新建運行/調(diào)試配置,如下圖:

上圖中的Program arguments中,-a選項代表api level,可以通過如下屬性獲得:

-d選項中的framework是從手機/system/framework拉取下來的框架層,-x選項為要反編譯的odex。
調(diào)試查找錯誤原因

報錯如下:
Error occurred while disassembling classLandroid.support.v4.util.TimeUtils; - skipping class
java.lang.RuntimeException: Invalid methodindex: 32
atorg.jf.dexlib2.analysis.InlineMethodResolver$InlineMethodResolver_version36.resolveExecuteInline(InlineMethodResolver.java:175)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeExecuteInline(MethodAnalyzer.java:1512)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeInstruction(MethodAnalyzer.java:982)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyze(MethodAnalyzer.java:205)
atorg.jf.dexlib2.analysis.MethodAnalyzer.<init>(MethodAnalyzer.java:140)
atorg.jf.baksmali.Adaptors.MethodDefinition.addAnalyzedInstructionMethodItems(MethodDefinition.java:463)
atorg.jf.baksmali.Adaptors.MethodDefinition.getMethodItems(MethodDefinition.java:371)
atorg.jf.baksmali.Adaptors.MethodDefinition.writeTo(MethodDefinition.java:238)
atorg.jf.baksmali.Adaptors.ClassDefinition.writeDirectMethods(ClassDefinition.java:282)
atorg.jf.baksmali.Adaptors.ClassDefinition.writeTo(ClassDefinition.java:112)
atorg.jf.baksmali.baksmali.disassembleClass(baksmali.java:225)
atorg.jf.baksmali.baksmali.access$000(baksmali.java:55)
atorg.jf.baksmali.baksmali$1.call(baksmali.java:149)
atorg.jf.baksmali.baksmali$1.call(baksmali.java:147)
atjava.util.concurrent.FutureTask.run(FutureTask.java:266)
atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
atjava.lang.Thread.run(Thread.java:745)
我們直接鎖定出錯的地方,在上面出錯信息標紅色的地方,并且在拋出異常處下斷點,我們可以判斷出錯原因是因為反編譯smali指令execute-line時傳入了一個未知的Dalvik虛擬機的內(nèi)部java方法索引inlineIndex=32:
而出錯地方所在的java類為InlineMethodResolver,從名字可以看出來該類是用于解析google原生dalvik虛擬機內(nèi)部java方法的類,我們順著代碼往前面找,
通過這兩處代碼,可以知道,通過傳入命令行參數(shù)T選項,我們就可以指定定制的dalvik內(nèi)部java方法而不采用原生android虛擬機的內(nèi)部java方法。
接下來的問題就是CustomInlineMethodResolver如何解析T選項傳進來的參數(shù)以及如何dump出dalvik內(nèi)部方法。
我們可以通過dvmGetInlineOpsTable這個libdvm.so的導(dǎo)出函數(shù)dump出內(nèi)部方法:
很幸運,smali作者已經(jīng)提供了dump內(nèi)部方法的工具deodexerant,只是該哥們沒有在網(wǎng)上提供任何關(guān)于該工具的正式說明而且網(wǎng)上沒有第三方文檔,而且這個T選項還是隱藏的。導(dǎo)致很難搜索到相關(guān)的信息。繞了一大圈,有木有。(PS:當然你也可以自己寫一個,工具已經(jīng)編譯好放文檔同目錄下面了)
反編譯odex
至此,我們按照如下步驟來反編譯odex:
首先,push deodexerant到手機上并運行生成inline.txt
然后,我們把inline.txt作為-T選項的參數(shù)傳遞進去:
完美反編譯。