odex 是經過優化的dex文件,且獨立存在於apk文件。odex 多用於系統預制應用或服務。通過將apk中的dex文件進行 odex,可以加載 apk 的啟動速度,同時減小空間的占用。請參考ODEX關於 odex 的說明。
在反編譯 odex 文件的過程中,我們需要使用到以下工具
smali/baksmali是odex與dex文件格式互相轉換的兩個工具,dex2jar則是將dex文件轉為java的jar文件,JD Compiler用於反編譯jar文件。也就是說,經過以上一系列的操作,我們最終可以從一個odex文件得到一個可讀的java文件。(事實上,也不是完全可讀,與源碼上還是有差別,有時候部分代碼還無法反編譯過來,只能以jdk虛擬機指令的方式存在了)。
首先,一個 odex 文件的生成過程是:java -> class -> dex -> odex,那么反編譯的就是上面過程的逆操作了:odex -> dex -> class -> java。
我的測試環境:
- Android 4.1.2
- Samsung Galaxy II
以Android系統中的 uiautomator.odex 文件為例,目標是反編譯其源碼(其實它的源碼grepcode).
工具准備
創建一個臨時目錄test,將 smali/baksmali 相關的工具都放入其中。
反編譯 (odex -> dex)
首先,將目標 odex 文件拿出來。
1
2
|
cd
test
adb pull
/system/framework/uiautomator
.odex
|
在合成 odex 文件過程中,還需要用到很多依賴文件,它們同樣也是 odex 格式的。因此在合成時,我們需要根據情況反復從手機中抽取相關的依賴包。
關於命令的使用,直接執行 java -jar baksmali-2.0.2.jar
可以得到相關的使用說明。這里要用到的參數主要是:
[-a | --api-level]
: Android API等級,Android 4.1.2是16[-x | --deodex]
: 操作,反編譯[-d|--bootclasspath-dir]
: 依賴包的目錄,我們用當前目錄.
開始反編譯,執行以下命令:
1
2
3
4
5
6
7
8
|
D:\
test
>java -jar baksmali-2.0.2.jar -a 16 -x uiautomator.odex -d .
Error occured
while
loading boot class path files. Aborting.
org.jf.util.ExceptionWithContext: Cannot
locate
boot class path
file
/system/framework/core-junit
.odex
at org.jf.dexlib2.analysis.ClassPath.loadClassPathEntry(ClassPath.java:217)
at org.jf.dexlib2.analysis.ClassPath.fromClassPath(ClassPath.java:161)
at org.jf.baksmali.baksmali.disassembleDexFile(baksmali.java:59)
at org.jf.baksmali.main.main(main.java:274)
|
以上的異常表明,反編譯的過程缺少依賴包/system/framework/core-junit.odex
,那就從系統中提取。
1
2
3
4
5
6
|
D:\
test
>adb pull
/system/framework/core-junit
.odex
# 重復
D:\
test
>java -jar baksmali-2.0.2.jar -a 16 -x uiautomator.odex -d .
# 如果還有缺失的依賴包,則反復從手機上提取
|
反編譯 uiautomator.odex 總共需要使用到以下依賴包:
1
2
3
|
D:\
test
>
ls
*.odex
android.policy.odex bouncycastle.odex core.odex framework.odex sec_edm.odex services.odex
apache-xml.odex core-junit.odex ext.odex framework2.odex seccamera.odex uiautomator.odex
|
baksmali 執行成功后,會產生一個 out
目錄,里面放的是中間文件。這時,可以使用這些中間文件來生成dex
文件:
1
2
3
4
5
|
D:\
test
>java -jar smali-2.0.2.jar -a 16 -o classes.dex out
## 解壓 dex2jar 到 test 目錄
D:\
test
\dex2jar-0.0.9.15>d2j-dex2jar.bat ..\classes.dex
dex2jar classes.dex -> classes-dex2jar.jar
|
classes-dex2jar.jar 便是我們要得到java jar包。通過JD Compiler打開這個jar可以看到反編譯后的java內容。
之所以反編譯 uiautomator,是因為Android SDK中給出的 uiautomator.jar 包中很多API都沒有包含其中,也沒有在其官方文檔中給予說明。通過閱讀 uiautomator 的源碼,發現它有很多可以擴展的地方。