首先,我們可以看到一張說明從apk到java的過程的圖片(圖1)。為了達到反編譯apk的最終目的,我們可以使用apktool、dex2jar、enjarify、jd-core( jd-gui )、cfr、procyon等工具。實際上,Apk可以看作是一個zip文件,其中的**DEX**是根據android系統中Dalvik或ART虛擬機優化后的Java字節碼。在獲取Java源代碼之前,我們需要將DEX轉換成等價的JAR。值得一提的是,我們可以認為Jar文件是封裝一系列Java classes的包。最后,我們可以使用java反編譯器:cfr、jd-core和procyon,三者中的任何一個都可以將JAR反編譯成非常接近源項目的java文件。
由于反編譯可能會出現錯誤,我們可以讓三種java反編譯器分別進行工作,結合三者的反編譯結果來降低錯誤率。
最后,不論如何**我們也不能將APK文件完全恢復成java的源代碼**,還需要用我們的智慧手動地調整代碼的細節,才能夠完全恢復成原來項目的模樣。更不要提,我們可能還會遇到混淆或者加固后的代碼,這更加會增加我們恢復源碼的難度。換句話說,這也是開發一個實用的反編譯器的核心點和難點。
:-: ![apk2java][1]
:-: 圖1.從Apk到java文件的流程圖
圖2顯示了Jar文件和Apk文件之間的區別。類文件本質上與dex文件相同,都是字節流的代碼文件。換句話說,dex源自class文件,因為DVM或ART-VM是基于JVM開發的。我們可以使用JDK工具中的javap來反編譯類文件,同樣地,我們可以使用apktool來反編譯dex文件。
:-: ![jar-apk-compare][2]
:-: 圖2.Jar文件和Apk文件的對比圖
## 1 從apk中獲取資源文件和smali代碼
### apktool
https://ibotpeaches.github.io/Apktool/
一個用于逆向工程的第三方工具,可以用來逆向封閉的、二進制的Android應用程序。它可以將資源解碼成幾乎原始的形式,并在進行一些修改后重新構建它們。它還讓應用程序使用起來變得更容易,因為APK項目本質上就是一個文件結構,我們可以將一些重復性的任務自動化,如構建apk等。
java -jar apktool.jar d yourapp.apk
## 2 從apk/dex中獲取jar文件
### 2.1 dex2jar
https://github.com/pxb1988/dex2jar
使用dex2jar 處理`.dex` 和java `.class`文件
./d2j-dex2jar.sh <your-classes.dex> -o <out-jar-file>
### 2.2 enjarify
https://github.com/google/enjarify
### 簡介
Enjarify是一個工具,用于將Dalvik字節碼轉換為等價的Java字節碼。這允許Java分析工具分析Android應用程序。
### 為什么不用dex2jar?
Dex2jar是一個較老的工具,它嘗試將Dalvik轉換為Java字節碼。在大多數情況下,它都運行得很好,但是很多模糊的特性或邊緣情況會導致它失敗,甚至無聲地產生不正確的結果。相比之下,Enjarify被設計用于盡可能多的情況,即使對于Dex2jar可能失敗的代碼也是如此。在其他方面,Enjarify能正確地處理unicode類名、多種類型的常量,進行隱式的強制轉換,能將異常處理程序跳轉到正常控制流,能處理引用太多常量的類,解析非常長的方法,甚至在應對catchall處理程序之后的異常以及錯誤類型的靜態初始值時,都能夠正常工作。
### 使用Python 3來運行它
Enjarify是一個純**python 3**應用程序,所以你可以直接運行它,你需要在命令行中進入到項目的根目錄中,然后運行:
python3 -O -m enjarify.main yourapp.apk
一般情況下,你可能希望使用腳本并將其配置在你的環境變量中。
為了方便起見,我們提供了一個編寫好的shell腳本`enjarify.sh`。如果可以的話,你可以嘗試使用Pypy,因為它比CPython更快。如果希望能夠在任何位置調用Enjarify,可以在路徑上的某個位置(比如~/bin)創建符號鏈接。為此,假設你位于項目的根目錄,
ln -s "$PWD/enjarify.sh" ~/bin/enjarify
### 在Windows操作系統中
我們提供了一個批處理腳本文件`enjarify.bat`。要從任何地方調用它,只需將該文件所處的目錄(也就是enjarify項目的根目錄)添加至系統的環境變量即可。批處理腳本將始終調用python3作為解釋器。如果您想使用pypy,請編輯該腳本文件。
### 使用方法
假設你正確地設置了路徑上的腳本,您可以通過鍵入enjarify從任何地方調用它。
enjarify yourapp.apk
最基本的使用方法是指定apk文件或dex文件作為輸入。如果apk中多個dex文件, Enjarify將自動轉換所有dex文件,并將結果輸出整合到一個jar中。如果指定一個dex文件,則只轉換該dex文件。例如,假設您可以手動提取dex文件:
enjarify classes2.dex
當前目錄中的默認輸出文件是`[inputname]-enjarify.jar`。如果要要指定輸出的文件名,請使用`-o`或`--output`選項。
enjarify yourapp.apk -o yourapp.jar
默認情況下,如果輸出文件已經存在,Enjarify將不會覆蓋它。若要覆蓋輸出,請傳遞`-f`或`--force`選項。
## 3 從Jar中獲取java代碼
### 3.1 jd-core
https://github.com/nviennot/jd-core-java
JD-Core是jd-gui使用的java反編譯器,但是它常常被忽視,人們往往會使用jd-gui,卻不知道它的反編譯引擎是什么。jd-core是開源的,我們可以用它快速完成反編譯工作。
JD-Core-Java是Java反編譯器的一個小部件。
這是通過破解IntelliJ IDE插件而獲得的。我們通過偽造IDE的接口,來提供對JD-Core的訪問。
java -jar jd-core.jar <compiled.jar> <out-dir>
### 3.2 cfr
http://www.benf.org/other/cfr/
CFR將對現代Java特性進行反編譯——包括大部分Java 9、10和更高版本,但完全是用Java 6編寫的,所以可以在任何地方使用——它甚至可以很好地將其他JVM語言的class文件轉換回java。
java -jar cfr.jar <compiled.jar> --outputdir <dir>
### 3.3 procyon
![procyon][3]
https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler
Procyon是一套專注于代碼生成和分析的Java元編程工具。它包括下列的庫:
1. 核心框架
2. 反射框架
3. 表達式框架
4. 編譯器工具箱(實驗功能)
5. Java反編譯器
procyon反編譯器是Java反編譯器的獨立前端,是procyon編譯器工具的一部分。
procyon的作者說:
>作為一名在.NET平臺和Java平臺之間來回奔波的開發人員,我對Java生態系統中能夠選擇的反編譯器感到驚訝和沮喪。Jad(不再維護,封閉源代碼)和JD-GUI (GPL3)是相當不錯的選擇,但是前者不支持Java 5+語言特性,而后者并不兼容我的LINQ/DLR樹編譯器。
>為了解決這個問題,我最近開始自己開發一個反編譯器,靈感來自(并大量借鑒)*ILSpy*和*Mono.Cecil*
java -jar procyon.jar <compiled.jar> -o <dir>
## 4 其他
### 4.1 Jeb (Android java反編譯工具,提供可視化的窗口)
https://www.pnfsoftware.com/
為專業人員提供的逆向工程的工具,能夠反編譯和調試二進制代碼,破解和分析文檔文件。
Dalvik, MIPS, ARM, Intel, WebAssembly & Ethereum反編譯器。
![jeb-gui][4]
當你第一次打開JEB時,可能會提示你沒有安裝相應的庫,你可以使用`sudo apt-get install`命令來修復它。
# sudo apt-get install libcarberra-gtk-module
### 4.2 IDA_Pro (C/.so 反匯編器)
https://www.hex-rays.com/
IDA是一款交互式的反匯編軟件:世界上最聰明、功能最全面的反匯編軟件,許多軟件安全專家都熟悉它。
IDA完全用C++編寫,可運行在三大操作系統上:Microsoft Windows、Mac OS X和Linux。
IDA也是我們的第二個產品Hex-Rays反編譯器的堅實基礎。
獨特的Hex-Rays反編譯器提供了二進制可執行程序的高級表示。它可以處理真實世界的代碼。它是真的。
![ida-gui][5]
當你第一次運行IDA時,可能會提示你有一些`missing libraries`,你可以運行下面的命令來安裝丟失的庫。在Linux系統上,IDA只支持32位(我的操作系統是Ubuntu x64),所以我們需要安裝相應的32位的庫才行。
```
$ sudo apt-get install multiarch-support
###安裝x86的支持庫
###libgthread-2.0.so.0
###libfreetype.so.6
###libSM.so.6
###libXrender.so.1
###libfontconfig.so.1
###libXext.so.6
$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 libglib2.0-0:i386 libfreetype6:i386 libsm6:i386 libxrender1:i386 libfontconfig1:i386 libxext6:i386
```
[1]: https://blog-1252789527.cos.ap-shanghai.myqcloud.com/article/Android%20decompiled%20process%20and%20tools/apk2java.png
[2]: https://blog-1252789527.cos.ap-shanghai.myqcloud.com/article/Android%20decompiled%20process%20and%20tools/jar-apk-compare.png
[3]: https://blog-1252789527.cos.ap-shanghai.myqcloud.com/article/Android%20decompiled%20process%20and%20tools/procyon.png
[4]: https://blog-1252789527.cos.ap-shanghai.myqcloud.com/article/Android%20decompiled%20process%20and%20tools/jeb-gui.png
[5]: https://blog-1252789527.cos.ap-shanghai.myqcloud.com/article/Android%20decompiled%20process%20and%20tools/ida-gui.png