轉自:https://cloud.tencent.com/developer/article/1548700?from=article.detail.1661891
今天給大家介紹一下Android App 在Java層的逆向工具。
逆向工具的介紹
在過去,當我們想要了解一個 app 內部運作細節時,往往先通過 ApkTool 反編譯 APK,生成 smali 格式的反匯編代碼[1],然后大佬和老手直接閱讀 smali 代碼,適當的進行修改、插樁、調試,經過一定的經驗和猜想,理解程序的運行邏輯和加解密細節,比如如下的 smali 代碼。

smail
我們只要先這樣,再那樣,最后再這樣,對對對,就這樣,一個程序的加密就被破解出來了。 是不是迫不及待想來一次App的逆向之旅了?


事實上,這種方式對小白實在不友好,有沒有更加友好的方式呢?當然是有的,如果你百度或者 google 搜索逆向相關的教程和分享,很容易就會發現下面這三個工具。在介紹工具之前,我們先補充一下APK結構的知識,我們以伊對這個社交 Apk 為例。
APK 文件其實是一種特殊的 zip 格式,我們可以直接用 360 壓縮或者別的壓縮工具打開。

為了滿足自身的功能和設計,幾乎每一個都會在基礎的文件結構上添加不少東西,但有六個部分是不變的,我們羅列和稱述一下。
文件或目錄 |
作用 |
---|---|
META-INF/ |
描述apk包信息的目錄,主要存放了簽名信息,配置信息,service注冊信息 |
res/ |
存放apk資源文件的目錄,比如圖片、圖標、字符串、樣式、顏色 |
assets/ |
同樣是存放apk資源文件的目錄,但和res有差異,和我們關系不大 |
resources.arsc |
資源索引,包含不同語言環境中res目錄下所有資源的類型、名稱與ID所對應的信息 |
lib/ |
存放so文件,越來越多的應用由C/C++編寫核心代碼,以SO文件的形式供上層JAVA代碼調用,以保證安全性,這個目錄是逆向解密關注的重點 |
classes.dex(一個或數個) |
Android程序運行在Dalvik虛擬機上,而dex就是Dalvik虛擬機的可執行文件, 相當於Windows平台中的exe文件,通過反編譯dex,可以獲得apk源碼(這個說法不很准確,但方便理解) |
AndroidManifest.xml |
清單文件,包含了App大量的的配置信息,比如包名、應用需要擁有的權限(打電話/錄音/網絡通信等等)、以及所有的界面和程序組件的信息,無法解壓apk時直接打開,因為清單文件在apk打包過程中被編譯成了二進制格式文件 |
接下來我們介紹以下反編譯工具,看一下反編譯工具的作用
工具 |
作用 |
---|---|
ApkTool |
解析resources.arsc,AndroidManifest.xml等文件,反編譯dex文件為smali源碼 |
Dex2jar |
將dex文件轉化為jar文件 |
Jd-gui |
反編譯jar,查看java源碼 |
比如使用 Dex2jar+Jd-gui, 最終得到這樣的結果。

是不是感覺友好很多?只需要cmd敲七八行命令就可以得到java源代碼。[2]
這樣做肯定沒問題,但能不能更加簡單一些呢?能不能直接將Apk拖到什么軟件里,然后電腦屏幕發亮,藍底黑字,日志和指令不停流淌,過一會兒完整的java代碼和apk結構就顯現出來?

前人種樹后人乘涼,真的有不少這樣的工具,通過這一類高集成度的逆向工具,我們可以方便快捷對Apk進行逆向分析。
這里介紹幾款:JADX,JEB,Android Killer,GDA。
1.1 Android Killer
首先說一下Android killer,這也是我接觸的第一個反編譯工具,開場界面非常酷。

它集成了Apktool,Jd-Gui等工具實現了拖拽式反編譯,功能強大,並且可以安裝插件,使用android killer進行smali一鍵插樁非常的暢爽。但由於更新慢,逐漸老舊,使用它反編譯apk越來越力不從心,而且它只可以在windows平台使用,所以我們這邊不做過多介紹,但不可否認它有一些非常棒的功能。
1.2 GDA
GDA是國人制作的一款反編譯神器,功能強大,靈活至極。 我們先說一下它的優點,僅2.6M大小,簡直不可思議,而且它不需要JDK環境,測試時反編譯七八十兆大的apk也不會卡死,除此之外,它還附帶有反混淆,查殼等功能……

接下來我們說一下它的缺點:
一、反編譯出來的java代碼展示性不夠友好,變量名不夠友好,大多是v0, v1, p1等(更像是原生寄存器的命名法)。
二、工具的文檔和文章不算充分,在搜索逆向工具教程時,比較難找到其相關介紹。
三、只能在windows平台運行和使用,不支持mac等其他平台,這很遺憾。
四、單論反編譯效果,JADX太好用了………………


1.3 JADX vs JEB
JADX:免費,開源,強大,更新快
優點:反編譯能力強,代碼結構好,變量名合理,支持多平台,完全就是個和我一樣完美的靚仔,是我心中逆向分析APK的第一工具。[3]
缺點:比較吃內存,一個50M大小的APK,使用JADX反編譯就需要占用4G左右內存。
JEB:收費,可動態調試
優點:可以動態調試,而且JEB吃內存比較少,反編譯同等大小的APK,JEB只要Jadx一半內存就可以搞定。同時,端口自動轉發帶來了舒適方便的動態調試體驗。
缺點:反編譯出來的java偽代碼展示性不夠友好,變量名不夠友好,大多是v0, v1, p1。
我們測試對比一下GDA,JEB,JADX三個軟件的反編譯效果 如圖:HttpRequestEntity這個構造方法[4]反編譯效果的對比



可以看出,JADX反編譯的結果最為接近正常的java代碼,在后續使用過程中,你還會發現它全局搜索功能的便捷和舒適。
接下來我們安裝一下這三個反編譯工具 鏈接:https://pan.baidu.com/s/1SDM9f2HxxbNzGg2XVBymPA 提取碼:i1k9

你可能會困惑,上面花了不是不少時間,分析和比較了幾個軟件的優缺點,又用證據說明了JADX是像你一樣的靚仔,那我們肯定毫不猶豫選擇你啊,呸,選JADX啊。為什么要三個都裝呢?
原因很簡單,在技術嫻熟和精通之前,APP逆向是門不折不扣的玄學,既然是玄學,就會有很多不可控、隨機、稀奇古怪的狀況。當JADX中一個變量模糊不清的時候,你就需要去JEB中看一下它的反編譯結果,或者使用JEB進行動態調試。當使用JEB 遇到頭疼的APK混淆時,就可以試一下開啟JADX的反混淆功能。因為這幾個軟件的逆向原理是不同的,所以在分析具體APK時各有優勢,它們的功能可以互補。多個工具結合使用可以一定程度彌補個人能力的不足,只需要幾百M空間放它們即可,何樂而不為呢。
1.4 JADX的配置和使用
直接下載,找個合適的地方解壓即可,按照自己的操作系統打開相應的文件即可。

可能出現的兩個問題:
- 為什么雙擊jadx-gui.bat 出現控制台一閃而過,沒有正確出現界面 因為你的JAVA_HOME環境變量沒有正確配置,但也不排除是JDK版本的問題。
- 反編譯卡死、閃退 Apk超過50M就很容易出現OOM(OutOfMemoryError),在win中,它默認使用4G內存,可以查看界面底部居中部分。

如果你的window系統是8G或者更高運行內存,我們可以修改參數進行擴容。文本模式打開jadx-gui.bat,將被框出的內容數值改為8g或者更大,如果電腦運行內存更大,也可以改成更高的數值。100M以內的App,8G內存足夠了。

接下來重新打開JADX,內存就已經更改了。

如果你的windows系統只有4G運行內存,我們依然有很多辦法使用jadx,實戰中再說。
接下來說一下mac中的擴容,文本模式打開jadx-gui這個文件,找到和上述類似的位置,更改為更大的值即可。
JADX的使用和快捷鍵
- 搜索代碼、類、方法——Ctrl+N,建議不要使用左上角的搜索類/搜索文本,因為圖標太小,很容易按錯,如果你第一次搜索用搜索類,第二次搜索時選擇搜索文本,那第一次的搜索內容和設置是不會記錄下來的。所以不如直接看一下工具欄中的快捷鍵,只用一個。
- 文件-首選項中,如果內存夠用,我建議勾選“自動進行后台反編譯”,因為Jadx默認只有在你展開內容或者搜索內容時,才會開始反編譯。不要勾選Unicode自動轉義,否則代碼中的中文會被轉成unicode,不方便識別和搜索。
- Ctrl+鼠標左鍵,可以跳轉到方法內部,幾乎所有的代碼編輯器都是這樣。
- 別的一些可以修改的地方我放在了下圖紅框里,比如反編譯線程數,線程數越多,反編譯越快,但占用內存也越多,建議根據電腦性能調整,不調整也OK。反混淆一般不用開。


1.5 JEB的配置和使用
同樣直接下載,找個合適的地方解壓,按照自己的操作系統打開相應的文件即可。 我們同樣要進行JEB的擴容,默認為1.8G,我們需要進行更改。

更改前

更改后
Windows中JEB的擴容

將整個紅框內容替換如下
:startjeb
set JEB="%~dp0bin\jeb1.exe"
if exist %JEB% goto :runlauncher
%JAVA% -jar -Xmx4g -Xms4g "%~dp0bin\app\jebc.jar" %*
exit 0
:runlauncher
%JEB% %*
exit 0
mac如何擴容我了解不多,如果遇到問題可以和我探討。
1.6 GDA的配置和使用
只有windows可以用,exe直接點開即可,以后會用到,到時候再說
[1]: Smali是dex文件反編譯的結果,可以說,smali語言是Dalvik的反匯編語言,下文會介紹DEX
[2]: 我們這一個系列的教程針對的是無殼App,而當你自己拿到一個未知的App時,第一步要做的一定一定得是查殼。
[3]: 得到的並不是Java源代碼,這是個錯誤的說法,但對初學者來說比較容易理解。不管你通過什么工具反編譯apk,得到的java代碼都和Apk開發時的源代碼相差甚遠。我們能得到的僅僅是一種偽代碼,它可能存在錯誤的邏輯、奇怪的變量名、各種各樣的error,但代碼總體上是靠譜的。
[4]: 為了閱讀和講解的循序漸進,我們這里並沒有把IDA考慮進來,IDA是神器,在后面是避免不了的。
[5]: 這條注釋針對沒有JAVA基礎的小伙伴,構造函數在JAVA中非常常見,JAVA是一門面向對象的語言,構造函數是一種特殊的函數。其主要功能是用來在創建對象時初始化對象, 構造函數與類名相同。如果聽不懂也沒關系,知道是個函數即可,后續也會慢慢補充JAVA知識。