Apk去簽名校正詳解

來源:互聯網
上載者:User

標籤:

  某些apk為了防止重打包,使用了簽名校正。所以在破解的時候我們需要破解簽名校正。在定位簽名校正位置時常用的關鍵詞有sign,signature,checkSign,signCheck,getPackageManager,getPackageInfo,verify,same等。  java層簽名校正程式碼範例:
 1 //原簽名資訊 2 private static final String SIGNATURE = "478yYkKAQF+KST8y4ATKvHkYibo="; 3 private static final int VALID = 0; 4 private static final int INVALID = 1; 5  6 public static int checkAppSignature(Context context) { 7     try { 8         PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),PackageManager.GET_SIGNATURES); 9 10         for (Signature signature : packageInfo.signatures) {11             byte[] signatureBytes = signature.toByteArray();12             MessageDigest md = MessageDigest.getInstance("SHA");13             md.update(signature.toByteArray());14             15             final String currentSignature = Base64.encodeToString(md.digest(), Base64.DEFAULT);16 17             Log.d("REMOVE_ME", "Include this string as a value for SIGNATURE:" + currentSignature);18 19             //compare signatures20             if (SIGNATURE.equals(currentSignature)){21                 return VALID;22             };23         }24     } catch (Exception e) {25         //assumes an issue in checking signature., but we let the caller decide on what to do.26 27     }28     return INVALID;29 }

    最近遇到一個進行了簽名校正的apk,它是在用戶端擷取簽名資訊然後在伺服器端進行簽名比對的,而且簽名的擷取是在native代碼中實現的。這種簽名校正的破解思路一般是在sd卡中儲存一個原apk包,修改apk路徑,讓程式擷取原apk的簽名資訊。修改辦法一般有三種,下面一一介紹。

(一)在java層修改context進行破解  首先安裝apk,啟動DDMS查看log資訊:     根據這個“verifyHashByC”這個字串猜測跟簽名校正有關係,於是在java層搜尋verifyHashByC,沒有找到對應的log列印處,只發現同名的native函數調用:      猜測此log列印資訊是在so中,於是找到該native函數對應的so載入處,發現載入的是libAppVerify.so這個動態庫:                  用ida開啟libAppVerify.so,搜尋verifyHashByC,在VerifyHash_BySha函數中發現了log日誌列印的代碼:                              光看函數名稱VerifyHash_BySha就知道是通過sha演算法驗證Hash,但是這是不是用於簽名校正的呢,利用ida的交叉引用查看函數調用關係,發現這個函數在VerifyHash(_JNIEnv *, char *, char const*, int)函數中被調用。而VerifyHash則是由前面提到的native函數verifyHashByC來調用的。     VerifyHash函數先擷取應用程式套件名,然後調用GetApkMFData函數:                            在該函數中擷取應用路徑,然後解壓應用安裝包,讀取裡面的MANIFEST.MF檔案內容,然後再進行簽名比對:         擷取apk路徑的範例程式碼如下:
 1 private static String getApkPath(String pkgName) {   2     PackageManager pm = mContext.getPackageManager();   3     ApplicationInfo pi = null;   4     try {   5         pi = pm.getApplicationInfo(pkgName,PackageManager.GET_UNINSTALLED_PACKAGES);   6         if(pi != null)   7             return pi.sourceDir;   8         else    9             return null;  10     } catch (NameNotFoundException e) {  11         e.printStackTrace();  12         return null;  13     }  14 }  

sourceDir儲存了apk的完整路徑:

 

   接下來,解壓apk,讀取MANIFEST.MF檔案:                              為MF檔案中的內容,與中記憶體單元的內容一致:               分析了這麼多,如何破解呢?通過前面的分析可知在so中擷取apk包的路徑的流程是:    傳入context,通過ApplicationInfo的sourceDir擷取到apk路徑,如果我們修改sourceDir讓它始終指向原apk,那麼我們的目的就達到了。通過反編譯java代碼,找到調用libAppVerify.so的地方,,context就是從這裡傳入的:            我們要做的就是修改這個context,使它最後指向的sourceDir為原apk路徑。                   根據原理,我們自己實現一個ApkApplicationInfo類指定sourceDir為原apk(SD卡中apk)路徑,ApkApplicationInfo在getApplicationInfo函數中執行個體化,由於getApplicationInfo函數為PackageManager類的成員函數,所以需要自己實現一個ApkPackageManager類(繼承自PackageManager類)來調用getApplicationInfo函數。ApkPackageManager類需要在getPackageManager函數中得到執行個體化,getPackageManager函數為Context的成員函數,所以還需要自己實現一個繼承自Context的類ApkContext。  於是,建立一個Android工程,建立ApkApplicationInfo、ApkPackageManager和ApkContext這三個類,設定sourceDir為“/sdcard/myapk.apk”。編譯後,將產生的apk反編譯,得到這的三個類的smali代碼檔案,如所示:     然後,將原apk反編譯,把上述三個檔案放入反編譯後的apk smali檔案夾中,在Lcom/rytong/emp/security/AppVerify類的verifyHash函數中插入下述代碼,:       重打包,安裝運行,成功!(二)使用hook技術  我們知道進行簽名校正是在libAppVerify.so中,所以我們只需hook這個so中的函數,更改傳入的apk路徑就行了。通過分析可知,該so是使用MINIZIP進行apk檔案解壓縮,然後擷取簽名資訊的。  使用MINIZIP進行apk檔案解壓縮的範例程式碼如下:
 1 void uncrypt_test() 2 { 3   //採用MINIZIP進行檔案解壓縮  4   unzFile uf=NULL; 5     unzFile data[1200]; 6     unz_global_info64 gi; 7     unz_file_info64 FileInfo;   8   9     //開啟zip檔案 10     uf = unzOpen64("D:\\myfile.zip");11     int result=unzGetGlobalInfo64(uf, &gi);12     if (result != UNZ_OK)          13         throw "檔案錯誤";14  15     //迴圈解壓縮檔案 16     for(int i=0;i<gi.number_entry;++i)17     {18         if (unzGetCurrentFileInfo64(uf, &FileInfo, 0, 0,NULL,0,NULL,0)!= UNZ_OK)19              throw "檔案錯誤";20  21         if(!(FileInfo.external_fa & FILE_ATTRIBUTE_DIRECTORY)) //檔案,否則為目錄 22             //開啟檔案23             //result=unzOpenCurrentFile(uf);/* 無密碼 */24             result=unzOpenCurrentFilePassword(uf,"123"); /* 有密碼 */25   26         //讀取內容27         int size= unzReadCurrentFile(uf,data,sizeof(data));                    28  29         //關閉當前檔案30         unzCloseCurrentFile(uf);   31  32         //出錯33         if(i < gi.number_entry - 1 && unzGoToNextFile(uf) != UNZ_OK)34           throw "error";        35     }36  37     //關閉流38     unzClose(uf);39 }

  從上述代碼可知,解壓過程中,apk路徑以參數形式傳入unzOpen64函數。所以我們需要hook這個函數。但是如何知道libAppVerify.so何時被載入呢?我們知道系統通過dvmLoadNativeCode函數從指定的路徑載入so,如果對系統函數dvmLoadNativeCode進行hook,當它載入libAppVerify.so的時候,再hook unzOpen64函數,修改apk路徑,不就行了?

  dvmLoadNativeCode函數原型:  

bool dvmLoadNativeCode(constchar* pathName, Object* classLoader, char** detail)

  這裡我們使用cydia substrate這個hook架構,關鍵代碼如下:

 將編譯產生的so檔案放到原apk lib目錄下。再通過java層進行載入,載入代碼如下:
1     const-string/jumbo v0, "substrate"2     invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V3     const-string/jumbo v0, "substrate-dvm"4     invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V5     const-string/jumbo v0, "HookVerify.cy"6     invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

由於需要在簽名校正代碼運行之前載入這些so,所以我們在Lcom/cgbchina/xpt/EMPView類的建構函式中添加上述代碼,如所示:

重打包簽名,安裝運行成功!(3)直接修改so檔案由於簽名驗證驗證的是MANIFEST.MF檔案,我們將原apk中MANIFEST.MF檔案改名為SIGNFILE.MF放到修改了的apk META-INF檔案夾下,然後將so中驗證的檔案名稱改為SIGNFILE.MF,:儲存,替換原so,重打包安裝,運行成功!

 

Apk去簽名校正詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.