回顧
《Android逆向小技巧③:批量注入日志,列印目標程式執行流程》
在上一篇2019年的文章中,我們使用python寫了一個簡單的文本處理工具:
https://github.com/encoderlee/android_tools
在使用apktool對目標應用的apk解包以后,用這個python寫的小工具,分析反編譯出來的smali代碼,并在每個方法中注入日志,然后對apk重新打包,這樣,但APP運行的時候,我們每做一個操作,都可以從日志中看出目標代碼的執行流程,
不過這種方式有一個很大的缺點,就是現在很多APP都做了簽名校驗,重新打包后,APP啟動時檢查到自身簽名不對,發現自己被重新打包了,就罷工不再作業了,
簽名校驗
以支付寶目前的最新版10.2.50 (2021-12-20) 為例,使用apktool重新打包后,你需要使用apksigner重新簽名才能安裝:
apksigner sign --v2-signing-enabled false --v3-signing-enabled false --ks encoderlee.jks alipay.apk
但是重新簽名簽的這個名,只能用自己生成的證書去簽名,因為你不可能搞到支付寶的證書和私鑰,
這個時候如果直接安裝運行這個APK,會出現這樣的問題:

抱歉,請求引數不合法,
其實這就是因為APP檢測到自身簽名不對,就拒絕服務的表現,有的APP會表現為閃退,
其實想想也很容易理解,apktool解包,修改,重新打包APP那么簡單,沒有哪個廠商愿意讓自己的APP被隨意的玩弄和修改,所以目前絕大多數的APP都做了簽名校驗,
常規對抗
常規的對抗思路是,既然你在代碼中做了簽名校驗,那么我找到你校驗簽名的代碼,通過修改smali檔案或用Xposed干掉它,不久OK了,于是你在網上可以搜到很多如何校驗簽名的代碼:
public static int verifySignature(Context context) {
boolean isValidated = false;
try {
//得到簽名
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(),PackageManager.GET_SIGNATURES);
Signature[] signs = packageInfo.signatures;
//將簽名檔案MD5編碼一下
String signStr = md5(signs[0].toCharsString());
//將應用現在的簽名MD5值和我們正確的MD5值對比
return signStr.equals("這里寫正確的簽名的MD5加密后的字串");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return isValidated;
}
本質上來說這些簽名校驗的代碼,都是呼叫 PackageManager.getPackageInfo().signatures 去獲取自身的簽名資訊,進行比較判斷自己是否被重新打包,
實際上,你在微信和支付寶反編譯出的代碼中,也能找到這些呼叫,但當你嘗試修改smali或用xposed干掉這些呼叫的,替換原版的 signatures 資料,就會發現:
并沒有什么卵用
想想也不可能那么簡單,微信支付寶可是和這幫打包者對抗多年了,實際上在微信支付寶中,還使用了多種手段來校驗自身簽名,其中就包括在so中使用本機代碼來實作校驗,這樣使得我們解決起來非常麻煩,
當然理論上來說,你完全可以找到它在so中檢驗簽名的代碼,干掉它,但是時間成本未免太高,看看微信支付寶的那個JAVA代碼量,以及so的數量,想在這些海量代碼中分析出關鍵點來,非常麻煩,就不要在這個思路上浪費時間了,
劍走偏鋒
那么,能不能找到一種通用的辦法,干掉大多數APP的簽名校驗呢?
我們先來分析,apksigner對APK簽名,本質上是做了什么事情?
我們可以比較apktool重打包后沒有簽名的APK檔案和apksigner簽名后的APK檔案,發現在APK檔案中多了一個【META-INF】目錄,里面的檔案保存的實際上就是簽名和檔案校驗資訊,
Android簽名原理可以看這篇文章:《Android 端 V1/V2/V3 簽名的原理》
而PackageManager.getPackageInfo().signatures獲取的signatures是什么?實際上就來自【META-INF】目錄中的【CERT.RSA】檔案(有的APK里面的RSA檔案不一定是這個名字,但都以.RSA結尾),里面有【包含公鑰的開發者證書】,證明這個APK是誰簽名的,
那么,我們直接把原版APK中的【META-INF】目錄下的【CERT.RSA】取出來,覆寫到我們打包后的APK中,不就可以了?這樣APK運行后,獲取到的signatures 仍然是支付寶自己原版的 signatures ,
理想是美好的,但是Android的這套簽名機制當然不會那么傻,這樣簡單替換【CERT.RSA】檔案后的APK,自然是無法正常安裝的,提示【INSTALL_PARSE_FAILED_NO_CERTIFICATES】錯誤,這是因為【CERT.RSA】不僅包含【開發者證書】也包含【對 CERT.SF 檔案的簽名】,我們重新打包APK后,【MANIFEST.MF】和【CERT.SF】都改變了,自然支付寶原版的簽名就和它對不上了,android系統在安裝的時候檢測到簽名對不上,自然就不允許安裝,
但要知道,Android系統是開源的,我們能不能修改Android系統源代碼,讓它允許安裝簽名錯誤的APK呢?當然是可以的,實際上也不需要這么麻煩,如果我們有root權限或有xposed,一樣可以Hook Android系統本身的代碼,讓Android系統跳過簽名校驗,安裝這個簽名錯誤的APK,
這樣的Xposed模塊早已有人寫好了,就是【幸運破解器「Lucky Patcher」】
https://www.luckypatchers.com/download/
幸運破解器有兩種方式來運行,一種是手機已經Root,一種是手機已裝好Xposed,
推薦Xposed的方式來運行,裝好幸運破解器后,在Xposed中勾選啟用該模塊,打開幸運破解器APP,
【工具箱】-》【Android核心破解】-》勾選【簽名驗證始終真實】,勾選【禁用ZIP簽名驗證】

一番操作后,我們就可以把重新打包后簽名不對的APK安裝到這個手機上,即使APP運行起來后,動態檢查簽名,也不會有什么問題,因為無論在JAVA層還是so層獲取signatures,最終都是從【CERT.RSA】讀取的資料,而【CERT.RSA】已經被我們替換成了支付寶原版的【CERT.RSA】,貨真價實,APP運行起來后動態檢測也不會發現什么例外,于是我們就可以正常運行我們重新打包修改過的微信支付寶APP了,當然其它大多數APP都可以這樣來搞,
注意!這種覆寫【CERT.RSA】檔案的方法,僅僅適用于V1簽名,所以我們上面使用
apksigner sign --v2-signing-enabled false --v3-signing-enabled false --ks encoderlee.jks alipay.apk
給APK前面的時候,禁用了V2 V3簽名,只保留V1簽名
(也許V2 V3也有對應的搞法?回頭有空再研究)
神器【VirtualXposed】
有人說,這種方式也太苛刻了吧,這樣一搞,雖然是個通用和萬能的方法破解了簽名校驗,但是要求安裝該APP的手機,必須是一個ROOT過的手機,或者裝了Xposed的手機呀,現在最新的小米華為手里,想要ROOT和Xposed,實在太麻煩了,而且我修改過的APP,想發布到群里給大家伙使用,不可能大家伙都要去ROOT手機吧?
那就要借助大名鼎鼎的 【VirtualXposed】了!
https://github.com/android-hacker/VirtualXposed
這個神器,可以在沒有Root權限的手機上創建一個虛擬環境,然后對該虛擬環境內的APP啟用Xposed模塊!
這個專案的作者真的是個天才,這個思路都被他想出來并且付諸實作了,
而且 【VirtualXposed】本身實際上已經集成了【幸運破解器「Lucky Patcher」】的【Android核心破解】功能,即允許在【VirtualXposed】中安裝簽名不對的APK,

我們只需要在【VirtualXposed】的【高級設定】中勾選【允許安裝沒有簽名的應用】
這樣就不需要【幸運破解器「Lucky Patcher」】了,絕大多數APK,我們使用apktool重新修改打包后,只需把原APK的簽名檔案【META-INF】覆寫回去,然后通過這樣的方式,安裝簽名不對的APK檔案,就可以暴力繞過APK簽名校驗,愉快的重新打包和分發各種APP了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/398045.html
標籤:AI
