把 Android App 逆向分為幾步?三步

  • 2019 年 11 月 20 日
  • 筆記

本文源於我近期的一次公司內部分享,通過逆向某款 App 來介紹逆向過程。由於僅作為學慣用途,App 的相關資訊會被遮蓋,敬請理解。

關於逆向

逆向 —— 包括但不限於通過反編譯、Hook 等手段,來解析一些功能的實現過程。

逆向在很多領域都有應用,比如如今爬蟲技術已經遍地走,甚至不用寫程式碼都可以爬取數據,導致前端開發的反爬意識也逐步提升。因此 JS、Android 等領域的逆向,已經成為爬蟲開發者必備的技能之一。

本文介紹的是最典型常見的傳參加密,在很多應用介面都能見到,如果我們逆向解析出加密過程,就可以模擬出相同的密文,得到後端介面的「認可」。

逆向的準備

這裡介紹下關於 Android 的逆向準備:

•Android 真機或模擬器(最好是真機)•安裝 Android 5.0 或 6.0 版本•Fiddler、Charles 等抓包工具•Jadx、ApkTool 等反編譯工具•dumpDex、FDex2 等脫殼工具•Java、Android 開發基礎知識•Xposed 框架開發基礎知識

逆向步驟

介紹一下本文逆向的步驟:

當然,用三步概括,看上去像「把大象塞進冰箱分為幾步」。逆向作為一項與應用開發者對抗的網路安全技術,其手段花樣多端,有時甚至不需要程式碼也可以完成逆向,所以這個概括僅對應文中的遇到情況。

定位目標

本次逆向是針對某款 App 的訂單介面,首先我們使用抓包工具捕獲訂單列表請求,下圖為 Charles 介面:

可以看到參數里的 data 欄位是密文,我們就使用這個 API 作為目標切入點。

反編譯 APK

這裡使用的反編譯工具是 Jadx,它可以將 APK 直接反編譯成 Java 程式碼,並且具有 GUI 介面方便操作,如下圖所示:

通過包名和一些程式碼分析,確定是被 360 加固後,接下來需要嘗試脫殼。

脫殼使用的是 FDex2,這是一款基於 Xposed 框架的 Hook 插件,對 360 加固比較有效。它的原理是 Hook ClassLoader,然後通過反射調用 getDex 方法獲取 Dex 對象並導出,這裡的 Dex 就是 App 真正執行的部分。當然並不是所有加固都可以被 Hook 到,更多脫殼手段還需要進階研究。

FDex2 使用方式很簡單,在 Xposed 框架里激活後,選擇目標 App,然後重新打開 App 後,被捕獲的 Dex 文件會被保存下來,如下圖所示:

Dex 是什麼?簡單地說,在 APK 構建過程中,Java 程式碼編譯後產生的 class 文件,需要再轉化成 Dex 文件,才能被 Android 虛擬機運行。

因此我們得到的 Dex 文件,就可以再次反編譯成 Java 程式碼,我們還是使用 Jadx,它同樣支援 Dex 格式。

由於 Dex 有體積限制,會被分包,如上圖我們導出了不止一個文件,可以依次載入它們,通過搜索目標 API 的關鍵詞,來找到目標程式碼塊,如下圖所示:

程式碼一般都會被反混淆,變數和方法名都是 a b c d 這樣,然後搜索一個方法名,會發現有一萬個同名的變數。還好 Jadx 內置了反混淆,開啟後變數和方法被重命名為唯一編號,這樣搜索時就不會有重名的情況了。

之後我們通過 Jadx 將程式碼導出成 Gradle 項目,藉助 IDEA 的強大功能開始進行程式碼分析。

分析程式碼

由於大部分方法都是被重命名的,導致可讀性嚴重下降,無法推測每個方法到底是什麼功能,如下圖這些程式碼:

第一眼你除了知道它是 Google 開發包之外,無法再獲得更多資訊。

所以分析程式碼這個步驟,完全是考驗你的 Java 基本功 + 耐心,二者缺一不可。

不過不要退縮,我們只要遵循一些技巧,就可以大幅減少工作量。由於分析過程比較繁瑣,這裡就不結合具體程式碼了,只做一些理論總結:

1.從目標 API 開始入手,跟蹤執行流程:比如我們剛才已經搜索到關鍵詞程式碼,那就從那一行開始,通過 IDEA 查看方法功能,可以一路向下點擊。2.只分析涉及程式碼塊,縮小分析範圍:請求過程通常會構建 Request 對象,那參數加密一定就在構建對象之前,我們只要找到構建 Request 對象的程式碼,然後查看加密參數被傳入之前都經過了怎樣的處理,其他程式碼全部無視。3.將部分程式碼塊複製出來進行執行:雖然反編譯的項目程式碼無法被整體執行,但對於冗長難懂的方法程式碼,我們可以連同相關程式碼一起複制到一個新項目中,進行編譯執行,方便我們調試。4.嘗試搜索一些關鍵詞:程式碼並不會所有都被混淆,可以嘗試全局搜索一些關鍵詞。比如 Java 常用的加密演算法,我們可以搜索 RSA、AES、MD5、Encrypt、public_*key 這些關鍵詞和正則匹配,能搜到再好不過了。

當你找到了加密方法,那麼可以複製出來獨立執行,然後自己構建參數傳入加密,通過模擬請求,看介面是否正常返回。

需要注意,如果不能正常請求,並不一定是你找錯了地方,也有可能程式碼本身有誤,反編譯的程式碼是有幾率會出現這種情況的,導致你執行的和 APK 執行的結果不同。遇到這種情況,只能通過其他手段來修正程式碼,如閱讀 Smali 程式碼、通過 Hook 等手段,這種情況展開又是長篇了,後續會有文章單獨介紹。

逆向之後

完成程式碼分析後,恭喜你已經成功完成一次逆向,接下來就可以實現一些功能,比如模擬登錄請求。建議直接使用 Java 程式碼,因為大部分加密用的是 Java 內置的 RSA / AES 加密演算法,其他語言的第三方庫實現並不充分。


至此本次逆向分享結束,逆向是一個大課題,本文由於篇幅原因,也只能將常見套路的大致流程介紹一下,後續一定追加更多細節部分的文章,歡迎各位關注本號。