Android 應用基於 Java/Kotlin 開發,編譯生成的字節碼(.class / .dex)保留了大量元數據:類名、方法名、字段名、行號等。這使得攻擊者能輕易使用反編譯工具(如 JADX、Apktool、dex2jar)將應用還原為高度可讀的源碼,導致核心業務邏輯、加密算法、API 金鑰等敏感信息洩露,甚至被二次打包注入惡意代碼。
代碼混淆 通過將可讀的符號重命名為無意義的短字符(如 a、b、c)、移除調試信息、優化控制流、加密字符串常量等手段,大幅提高逆向分析難度,是發布正式版應用前的必備安全措施。
proguard-rules.pro。現代項目建議直接使用 R8,僅在遇到兼容性問題時回退至 ProGuard。
在模塊級 build.gradle 中:
android {
buildTypes {
release {
minifyEnabled true // 開啟代碼壓縮/混淆
shrinkResources true // 同步移除無用資源
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
混淆會破壞反射、JNI、序列化、第三方庫調用等依賴具體名稱的場景,必須通過 -keep 系列規則保護關鍵代碼:
| 規則 | 作用 | 典型場景 |
|---|---|---|
-keep class ... | 保留類及成員,不重命名、不移除 | JNI 調用類、反射實例化類、Parcelable 實現類 |
-keepclassmembers class ... | 保留類成員,類名可混淆 | Enum 的 values()/valueOf()、Gson 序列化字段 |
-keepclasseswithmembers class ... | 同時滿足類名與成員條件才保留 | 特定註解標記的類 |
-keepnames / -keepclassmembernames | 僅防重命名,允許移除無用代碼 | 需保留名稱供外部識別但可優化的類 |
# 1. 四大組件、Application、自定義 View 等入口類
-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.view.View {
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
# 2. 序列化與 Parcelable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# 3. Gson / Jackson / Fastjson 實體類
-keepclassmembers class com.yourpackage.model.** { *; }
# 或使用註解方式:@Keep / @SerializedName 配合 -keepattributes *Annotation*
# 4. WebView JS 交互接口
-keepclassmembers class * {
@android.webkit.JavascriptInterface ;
}
# 5. Native (JNI) 方法
-keepclasseswithmembernames class * {
native ;
}
# 6. 保留行號資訊(利於線上崩潰定位)
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
ClassNotFoundException、NoSuchMethodError 堆疊,補全對應 -keep 規則。consumerProguardFiles,無需手動添加;若發現衝突,可嘗試 -dontwarn 抑制警告。mapping.txt 反向映射還原堆疊信息。Android Studio Analyze → Analyze Stack Trace 可直接粘貼混淆後堆疊 + mapping.txt 自動還原。minifyEnabled 僅對 release 生效,調試階段不影響開發效率。R8 默認啟用 proguard-android-optimize.txt,包含方法內聯、類合併、無用代碼消除等激進優化。若遇到兼容性問題,可在 proguard-rules.pro 添加:
# 關閉特定優化 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 或完全禁用優化(僅混淆+壓縮) -dontoptimize
代碼混淆不是「一勞永逸」的銀彈,但能將逆向成本提升數個數量級。建議:
minifyEnabled true 並完善保留規則;mapping.txt 歸檔,便於線上問題排查;參考資源:Android 官方文檔 - 縮減、混淆和優化應用 | ProGuard 官方手冊