很久沒有更新博客了,由於一些特操蛋的事情,一直沒有心思寫。上兩週終於把《Android 軟件安全與逆向分析》 看完了,而後就總是想找個 apk 練練手,可是水平太差,稍微加密就啃不動了。恰好遇到了這個 apk 習慣性逆向分析。java
傳送門:"**遊"強制更新破解android
前幾天客戶有提到一個做弊工具,因此就想下載體驗一下。結果下載的應該是一個較早的版本須要強制更新到最新版本,否則不能運行。
更新提示:
因此就想破解一下他的強制更新練練手,由於感受不難。json
利用 jadx-gui
反編譯 apk,jadx-gui
這個工具仍是挺好用的。一條命令就能夠看到反編譯後的 Java 代碼,還有資源文件。安全
Application
是 Android 程序的主入口,也是分析 apk 的開始點。並且經過運行程序也能夠發現。跳出的升級的 Dialog 是在程序運行後第二個頁面跳出的,第一個頁面爲啓動頁面。因此重點分析對象就是 Application
到第二個頁面。 AndroidManifest
查找 application
標籤看有沒有自定義 Application
網絡
過濾 android.intent.action.MAIN
查找第一個頁面。
app
自定義的 Application
中沒有什麼信息,只是作了一些配置的初始化和第三方 SDK 初始化的。函數
SplashActivity
是 apk 的第一個頁面也就是啓動頁面,由於代碼沒有作混淆處理,其中咱們仍是能夠發現一些關鍵的代碼。
變量 isUpdate
是關鍵點,也能夠發現這個頁面停了100ms後會跳轉到 MainActivity
頁面。可是這個頁面只是對變量 isUpdate
進行了判斷賦值沒有進行升級的處理。工具
MainActivity
真正的主頁面,查看 onCreate
方法。
當時只看到了第二個標註的代碼,心想這不是改下 if-else
的事嗎。(下面會將第一個標註)ui
apktool
反編譯 APK,沒有作過加固處理直接。定位到 MainActivity.onCreate
方法,修改if-else
邏輯,將if-eqz v3, :cond_3
改成如下代碼:
本來爲 isUpdate
爲 true
時,執行 isUpdateAlert()
方法。改成 false
時執行。 順便還加了一個 Log,回編安裝運行。
結果發現本身仍是太年輕,沒有繞過升級。雖然Log是有打印了,證實代碼是沒有問題的,可是在升級的 Dialog 仍是出現了,而且以前還有一個 Dialog。
那天研究太晚了就睡覺去了。this
次日想一想確定是本身哪裏分析錯了,又從新看了一遍代碼。首先看下以前認爲是改變邏輯後執行的函數 isUpdateAlert()
:
能夠看到當用戶點擊肯定的時候只改變了 SplashActivity.isUpdate
的值,沒有其餘操做了。再查找一下 R.string.str_reminder
的值在目錄 res/values-zh/strings.xml
:
好吧事實證實本身還太年輕啊。
因此能夠先回到 SplashActivity
看看變量是怎麼賦值的。
能夠看到 isUpate
的值是根據 Initialized 文件中保存的值跟當前APK的版本作比較獲得的值。
方法 setInitFlag
則是將當前版本寫入 Initialized。這樣看來貌似 isUpdate
不可能爲 true
了。 再看下什麼地方調用了這兩個函數:
到這裏能夠明白了,Initialized 文件是寫入當前版本號,可是當apk更新後版本號變了,跟 Initialized 中的版本號就不同了。因此 isUpdate
記錄的是當前 APK 是否是已經更新過了而且第一次打開,而不是當前 APK 是否是須要更新。
經過從新分析能夠判定以前的修改是錯誤的了,可是既然 APK 須要判斷是否須要更新那麼就必須有網絡請求,burp 該上場了,掛上代理打開APK:
這裏請求成功的只有三個 HTTP 請求(百度地圖的忽略),HTTP 還省了導入證書了。一個一個分析請求的 response 。抓包這個技能仍是必須掌握的:
知道了哪一個接口調用的那就簡單了,直接找出這個接口的類:
用的友盟的更新模塊,因此我上面忽略的纔是真正的更新代碼。
UmengUpdateAgent.setUpdateOnlyWifi(false); UmengUpdateAgent.forceUpdate(this);
再看 com.umeng.update.UpdateResponse
這個類的 a(JSONObject)
方法:
對比返回的 response (burp複製出來中文亂碼了,看key就好)
{ "update": "Yes", "version": "12.1.2", "path": "http://au.apk.umeng.com/uploads/apps/5386ea3b6c738f0de0000025/_umeng_%40_188_%40_09e2ea839754f61d4fb24ddb96a638bf.apk", "origin": "", "update_log": "天ä¸æ¸¸12.1.2\r\n1.ä¿®å¤å°ç±³5ä¸è½ä½¿ç¨çé®é¢\r\n2.éä½çµéæ¶èãæé«ç¨³å®æ§åå ¼å®¹æ§\r\n3.æ´æ°ä¼æ¸ é¤12.0以åçæ¬æ°æ®\r\n4.æ´æ°å®æå请éå¯ææºï¼ä»¥ä½¿æ´æ°çæï¼ï¼ï¼\r\n5.å¦éå°ä¸è½ä½¿ç¨çæ åµï¼è¯·å°âé®é¢åé¦âä¸æè¿°é®é¢å¹¶çä¸æ¨çèç³»æ¹å¼", "proto_ver": "1.4", "delta": false, "new_md5": "09e2ea839754f61d4fb24ddb96a638bf", "size": "18278969", "patch_md5": "", "target_size": "18278969", "display_ads": false }
因此這個類就是處理返回值的地方了。這不是修改一下 Yes
字符串就完了,哈哈哈哈哈哈。
添加了Log 將 Yes
改成 No
:
回編 安裝 運行,終於再也不提示更新了。。。。。。。
逆向分析真是一個細緻活啊,稍微有點忽略就走了彎路。另外對於 release 的版本的APK 最好能夠進行 proguard 混淆和加固,如今有不少第三方加固都提供免費的服務了,作了這兩步我想就能擋住不少像我這樣的菜鳥了。 好久沒更新博客,這篇也寫了好幾天才寫好。。。。。。。。。