標籤:混淆 android
什麼是代碼混淆
Java 是一種跨平台的、解釋型語言,Java 原始碼編譯成中間”位元組碼”儲存於 class 檔案中。由於跨平台的需要,Java 位元組碼中包括了很多原始碼資訊,如變數名、方法名,並且通過這些名稱來訪問變數和方法,這些符號帶有許多語義資訊,很容易被反編譯成 Java 原始碼。為了防止這種現象,我們可以使用 Java 混淆器對 Java 位元組碼進行混淆。
混淆就是對發布出去的程式進行重新組織和處理,使得處理後的代碼與處理前程式碼完成相同的功能,而混淆後的代碼很難被反編譯,即使反編譯成功也很難得出程式的真正語義。被混淆過的程式碼,仍然遵照原來的檔案格式和指令集,執行結果也與混淆前一樣,只是混淆器將代碼中的所有變數、函數、類的名稱變為簡短的英文字母代號,在缺乏相應的函數名和程式注釋的況下,即使被反編譯,也將難以閱讀。同時混淆是無法復原的,在混淆的過程中一些不影響正常啟動並執行資訊將永久丟失,這些資訊的丟失使程式變得更加難以理解。
混淆器的作用不僅僅是保護代碼,它也有精簡編譯後程式大小的作用。由於以上介紹的縮短變數和函數名以及丟失部分資訊的原因, 編譯後 jar 檔案體積大約能減少25% ,這對當前費用較貴的無線網路傳輸是有一定意義的。
混淆檔案 proguard.cfg 參數詳解
-optimizationpasses 5 # 指定代碼的壓縮層級-dontusemixedcaseclassnames # 是否使用大小寫混合-dontskipnonpubliclibraryclasses # 是否混淆第三方jar-dontpreverify # 混淆時是否做預校正-verbose # 混淆時是否記錄日誌-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆時所採用的演算法-keep public class * extends android.app.Activity # 保持哪些類不被混淆-keep public class * extends android.app.Application # 保持哪些類不被混淆-keep public class * extends android.app.Service # 保持哪些類不被混淆-keep public class * extends android.content.BroadcastReceiver # 保持哪些類不被混淆-keep public class * extends android.content.ContentProvider # 保持哪些類不被混淆-keep public class * extends android.app.backup.BackupAgentHelper # 保持哪些類不被混淆-keep public class * extends android.preference.Preference # 保持哪些類不被混淆-keep public class com.android.vending.licensing.ILicensingService # 保持哪些類不被混淆-keepclasseswithmembernames class * { # 保持 native 方法不被混淆 native <methods>;}-keepclasseswithmembers class * { # 保持自訂控制項類不被混淆 public <init>(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); # 保持自訂控制項類不被混淆}-keepclassmembers class * extends android.app.Activity { # 保持自訂控制項類不被混淆 public void *(android.view.View);}-keepclassmembers enum * { # 保持枚舉 enum 類不被混淆 public static **[] values(); public static ** valueOf(java.lang.String);}-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆 public static final android.os.Parcelable$Creator *;}-keep class MyClass; # 保持自己定義的類不被混淆
代碼混淆的方法
根據 SDK 的版本不同有 2 中不同的代碼混淆方式,以上的 proguard.cfg 參數詳解中所涉及到的資訊是在較低版本 SDK 下的混淆指令碼,事實上在高版本的 SDK 下混淆的原理和參數也與低版本的相差無幾,只是在不同 SDK 版本的環境下引入混淆指令碼的方式有所不同。具體方法如下:
- 低版本 SDK 下,項目中同時包含 proguard.cfg 和 project.properties 檔案,則只需在 project.properties 檔案末尾添加 proguard.config=proguard.cfg 再將項目 Export 即可。
- 高版本 SDK 下,項目中同時包含 proguard-project.txt 和 project.properties 檔案,這時需要在 proguard-project.txt 檔案中進行如下資訊的配置,然後再將項目 Export 即可。下面以真實的檔案進行示範說明。
# This file is automatically generated by Android Tools.# Do not modify this file -- YOUR CHANGES WILL BE ERASED!## This file must be checked in Version Control Systems.## To customize properties used by the Ant build system edit# "ant.properties", and override values to adapt the script to your# project structure.## To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txtproguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt# Project target.target=android-16
以上的配置資訊即是 project.properties 檔案中內容,藍色文字為我們在代碼混淆過程中需要添加的配置資訊,其中:sdk.dir 為你在當前機器上 SDK 的安裝路徑。如果想保留某個包下的檔案不被混淆,可以在 proguard-project.txt 檔案中加入保留對應包名的語句即可。
# To enable ProGuard in your project, edit project.properties# to define the proguard.config property as described in that file.## Add project specific ProGuard rules here.# By default, the flags in this file are appended to flags specified# in ${sdk.dir}/tools/proguard/proguard-android.txt# You can edit the include path and order by changing the ProGuard# include property in project.properties.## For more details, see# http://developer.android.com/guide/developing/tools/proguard.html# Add any project specific keep options here:-dontwarn com.cnki.android.cnkireader.** -keep class com.cnki.android.cnkireader.** { *; }# If your project uses WebView with JS, uncomment the following# and specify the fully qualified class name to the JavaScript interface# class:#-keepclassmembers class fqcn.of.javascript.interface.for.webview {# public *;#}
Android 編程下的代碼混淆