Android反編譯apk修改版本號重新打包簽名詳細教學(超詳細)

2020-10-01 16:00:13


最近突然有個緊急需求,應用的某一個版本釋出到應用寶時,由於應用寶自己抓包上傳了一個高版本的安裝包(即比當前要釋出的版本高),導致上傳失敗,而嚮應用寶申訴無果,我這沒有專案原始碼,找三方改東西太慢,所以要將這個版本反編譯、修改為更高版本號、重新打包、對齊、簽名在釋出到應用市場,特此整理一些心得。

一、反編譯工具介紹

1:apktool 獲取資原始檔

Apktool是一個逆向android非常有用的工具,可以用來反編譯apk檔案,並且能在修改部分資原始檔後,重新打包成一個新的apk。

2:dex2jar(原始碼檔案獲取)

將Android的包dex檔案轉換成jar檔案,此時拿到的時位元組碼檔案一般和jd-gui結合使用,將位元組碼檔案轉成對應的原始碼

3:jd-gui 檢視APK中classes.dex轉化成出的jar檔案,即原始碼檔案

將dex2jar中的jar(位元組碼)檔案轉成原始碼,既可以檢視原始碼也可以進行修改。

我的需求只涉及修改版本號,而不需要修改原始碼,只需要通過apktool工具反編譯拿到資原始檔、修改版本號、重新回編打包成apk、記憶體對齊以及重簽名 下面詳細介紹apktool的使用過程,dex2jar和jd-gui的使用將單起一篇文章進行介紹。

二、apktool工具的反編譯重打包簽名的詳細過程

首先下載一個最新版的apktool.jar

1:使用apktool.jar進行反編譯

新建一個apktool.bat指令碼 放入如下內容:

if "%PATH_BASE%" == "" set PATH_BASE=%PATH%
set PATH=%CD%;%PATH_BASE%;
chcp 65001 2>nul >nul
java -jar -Duser.language=en -Dfile.encoding=UTF8 "%~dp0\apktool.jar" %*

新建bat檔案很簡單直接將txt檔案另存為.bat檔案即可
在這裡插入圖片描述對apk包進行反編譯,將apk包和bat檔案(apktool.jar)放到同一個資料夾下,目的是為了輸入方便,只需要輸入相對路徑即可,如果不放到同一個資料夾下,每次輸入命令都要輸入絕對路徑。在這裡插入圖片描述
在cmd終端,cd到此目錄下,輸入以下命令:

**
 注意
 * outDir :表示反編譯後的資原始檔存放到哪個目錄下
 * source.apk :表示要進行反編譯的apk檔名稱
 */
apktool.bat d -o outDir source.apk

或者也可以通過下面的命令反編譯兩者實現的效果都是相同的
 java -jar apktool.jar d -f source.apk -o outDir 

執行完成後就會在當前目錄下生成outDir資料夾存放反編譯後生產的資原始檔
在這裡插入圖片描述

2:修改版本號versionCode

有了這個outDir就能修改裡面的東西了,最難修改的部分就是java程式碼,這裡對應的是smali相關的資料夾,需要了解一些smali的語法才行。
修改應用版本號只需要修改apktool.yml即可,apktool.yml檔案中找到versionCode,修改裡面的versionCode對應的值儲存即可。
在這裡插入圖片描述

3:通過修改後的檔案重新回編成apk檔案

然後就是再使用下面的命令列,可以將我們的outDior資料夾重新編譯成一個apk檔案,也就是下面命令中的new_no_singnalign.apk

**
 注意
 * new_no_singnalign.apk :新生成的apk檔案,此apk檔案沒有簽名和對齊
 * outDir :將outDir的檔案進行編譯
 */
apktool.bat b -o new_no_signalign.apk outDir

在這裡插入圖片描述

4:將新的apk檔案進行重簽名以及記憶體對齊
1:簽名工具:jarsigner和apksigner

此處簡單介紹一下Android用的簽名工具,以及V1(Jar Signature) V2(Full APK Signature)兩種簽名

  1. Android中對APK簽名是通過jarsigner或apksigner進行的;
  2. jarsigner是JDK提供的針對jar包簽名的通用工具位於JDK/bin/jarsigner.exe;
  3. apksigner是Google官方提供的針對Android apk簽名及驗證的專用工具,位於Android SDK/build-tools/SDK版本/apksigner.bat;

在AS打包Build->Generate signed apk… 打包簽名過程中,可以看到兩種簽名選項 V1(Jar Signature) V2(Full APK Signature),從Android 7.0開始, 谷歌增加新簽名方案 V2 Scheme (APK Signature);但Android 7.0以下版本, 只能用舊簽名方案 V1 scheme (JAR signing)

2:V1和V2簽名的區別

V1簽名:

  • 來自JDK(jarsigner), 對zip壓縮包的每個檔案進行驗證, 簽名後還能對壓縮包修改(移動/重新壓縮檔案)
  • 對V1簽名的apk/jar解壓,在META-INF存放簽名檔案(MANIFEST.MF, CERT.SF, CERT.RSA),
  • 其中MANIFEST.MF檔案儲存所有檔案的SHA1指紋(除了META-INF檔案), 由此可知: V1簽名是對壓縮包中單個檔案簽名驗證

V2簽名:

  • 來自Google(apksigner), 對zip壓縮包的整個檔案驗證, 簽名後不能修改壓縮包(包括zipalign),
  • 對V2簽名的apk解壓,沒有發現簽名檔案,重新壓縮後V2簽名就失效, 由此可知: V2簽名是對整個APK簽名驗證

V2簽名優點很明顯:

簽名更安全(不能修改壓縮包)
簽名驗證時間更短(不需要解壓驗證),因而安裝速度加快

注意: apksigner工具預設同時使用V1和V2簽名,以相容Android 7.0以下版本

3:zipalign記憶體對齊

位於Android SDK/build-tools/SDK版本/zipalign.exe zipalign;是對zip包對齊的工具,使APK包內未壓縮的資料有序排列對齊,從而減少APP執行時記憶體消耗

zipalign -v 4 in.apk out.apk //4位元組對齊優化
zipalign -c -v 4 in.apk  //檢查APK是否對齊

非常重要:

在此處介紹一下v1和v2簽名以及zipalign記憶體對齊,至於先簽名後對齊,還是先對齊後簽名與你採用的簽名方是有關係,
1:zipalign可以在V1簽名後執行,但zipalign不能在V2簽名後執行,只能在V2簽名之前執行!!!
2:如果不好記你就記住一個原則就是:先對齊後簽名

有了上面概念理論介紹,接下來就直奔主題進行實操了,接下來我就按照先對齊後簽名的方式分別用V1和V2進行簽名,至於V1簽名的先簽名後對齊的方式不在這裡描述了,感謝興趣的自己可以試試。

我們可以通過zipalign -c -v 4 new_no_signalign.apk //檢查APK是否對齊
在這裡插入圖片描述此命令執行完成後可以看到 Verification FAILED,表示沒有對齊。

通過zipalign -v 4 new_no_signalign.apk new_align.apk //4位元組對齊優化
在這裡插入圖片描述在這裡插入圖片描述

4:jarsigner給apk簽名,只支援V1簽名

jarsigner -verbose -keystore android.zhumu.keystore -signedjar (簽名後的apk路徑及名稱) (要給誰簽名.apk路徑 ) 簽名檔案的別名

在這裡插入圖片描述執行上面的命令後需要先輸入簽名檔案的密碼才能生成簽名檔案, 最終生成的singnedv1.apk就是我們最終要用的apk檔案。

5:apksigner給apk簽名,預設同時使用V1和V2簽名

cd到Android SDK/build-tools/SDK版本/目錄下, 輸入命令 apksigner sign --ks 金鑰庫名 --ks-key-alias 金鑰別名 --out 生成的簽名檔案路徑及名稱 給哪個apk檔案簽名
注意:
1:上面面引數中 金鑰庫名、給哪個apk檔案簽名 需要給出絕對路徑,要不就報錯早找不到檔案,因為在當前目錄下沒有簽名檔案和要進行簽名的apk檔案
2:而生成的簽名檔案路徑及名稱 如果不指定路徑就生成在當前目錄下

在這裡插入圖片描述

生成的singnedV2.apk就是最終要用的APK,注意4和5是兩種簽名方式用哪一種都可以。

6:驗證是否簽名成功

方案1只支援校驗v1簽名:
keytool -printcert -jarfile singnedv1.apk //此命令只支援校驗v1簽名
方案2支援v1和v2的簽名校驗:
apksigner verify -v --print-certs (apk地址)
需要切cd 到apksigner所在的目錄
如:apksigner verify -v --print-certs C:\Users\tiansc\Desktop\apks\signedV2.apk

5:檢視新生成的簽名apk的版本號是否修改成功

需要用到aapt工具看看新的apk的版本號是不是真的修改成功了,
輸入下面的命令分別對singnedv1.apksignedV2.apk分別進行檢視

aapt dump badging 要驗證的apk
如:
aapt dump badging singnedv1.apk
aapt dump badging signedV2.apk

在這裡插入圖片描述

三、總結

而在我們平時工作中關於APK的打包以及簽名都由AS工具視覺化一鍵完成了,逆向開發這塊需要對APK的打包簽名的流程有較為深刻的理解,只有這樣才能一步一步的手動完成反編譯、打包、簽名的整個過程。
本文章只是著重介紹了反編譯工具apktool的使用,至於dex2jar和 jd-gui工具將會另起一篇文章進行詳細介紹,敬請關注!!!