Giới thiệu
Đã bao giờ bạn gặp hoặc tự mình hỏi những câu hỏi như thế này:
Ứng dụng của mình vừa lên Store đã bị clone thế nhở?
Làm sao để che giấu mã nguồn của ứng dụng vô cùng xịn xò này?
Làm thế nào để làm cho việc thực hiện mã hóa ứng dụng trở nên đơn giản?
Nếu tôi chỉ muốn bảo vệ APK ở mức cơ bản nhất thì có cách nào nhanh hơn không?
Mở đầu
Để trả lời những câu trả lời ở trên thì mình sẽ phải trả lời câu hỏi: “Vậy thì, mã hóa mã nguồn để làm cái gì nhỉ?”
Khi bạn mã hóa, code bên trong APK sẽ được đảo lộn theo quy luật mà bạn đặt ra. Điều này khiến các Cracker/Hacker sẽ mất nhiều thời gian hơn để “luộc” được ứng dụng của bạn. Mã hóa chỉ có tác dụng kéo dài thời gian, làm nản chí các đại ca Crack/Decompile thôi nhá. Chứ chả có quả quýt nào lại không có người “thịt” được cả 😆.
Để làm được điều này, Android Studio đã cung cấp sẵn cho chúng ta một công cụ là Proguard – một công cụ hoàn toàn miễn phí. Ngoài ra, để có thể có thể bá đạo hơn về việc này thì có thêm một lựa chọn nữa là dùng bản trả phí như DexGuard.
Ngày hôm nay, mình sẽ giới thiệu cho các bạn cách mã hóa Proguard nhanh chóng, không cần nỗ nực. Công việc chỉ cần Copy + Paste, chỉnh sửa cho phù hợp với dự án và bắt đầu build app.
-ignorewarnings -renamesourcefileattribute SourceFile -keepattributes SourceFile,LineNumberTable -keepattributes Signature -keepattributes *Annotation* # EventBus -keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } # Only required if you use AsyncExecutor -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { <init>(java.lang.Throwable); } # Glide -keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } # ButterKnife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; } # AndroidUtilCode -keep class com.blankj.utilcode.** { *; } -keepclassmembers class com.blankj.utilcode.** { *; } -dontwarn com.blankj.utilcode.** # Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and # EnclosingMethod is required to use InnerClasses. -keepattributes Signature, InnerClasses, EnclosingMethod # Retrofit does reflection on method and parameter annotations. -keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations # Keep annotation default values (e.g., retrofit2.http.Field.encoded). -keepattributes AnnotationDefault # Retain service method parameters when optimizing. -keepclassmembers,allowshrinking,allowobfuscation interface * { @retrofit2.http.* <methods>; } # Ignore annotation used for build tooling. -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement # Ignore JSR 305 annotations for embedding nullability information. -dontwarn javax.annotation.** # Guarded by a NoClassDefFoundError try/catch and only used when on the classpath. -dontwarn kotlin.Unit # Top-level functions that can only be used by Kotlin. -dontwarn retrofit2.KotlinExtensions -dontwarn retrofit2.KotlinExtensions$* # With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy # and replaces all potential values with null. Explicitly keeping the interfaces prevents this. -if interface * { @retrofit2.http.* <methods>; } -keep,allowobfuscation interface <1> # Keep inherited services. -if interface * { @retrofit2.http.* <methods>; } -keep,allowobfuscation interface * extends <1> # With R8 full mode generic signatures are stripped for classes that are not # kept. Suspend functions are wrapped in continuations where the type argument # is used. -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation # R8 full mode strips generic signatures from return types if not kept. -if interface * { @retrofit2.http.* public *** *(...); } -keep,allowoptimization,allowshrinking,allowobfuscation class <3> -keep class com.google.gson.stream.** { *; } -keep class com.google.gson.reflect.TypeToken { *; }
buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
Chú ý khi sử dụng
Bạn phải bật option minifyEnabled để kích hoạt cơ chế mã hóa.
Bạn cần keep những class/package được sử dụng bằng phương pháp reflection. Vì sau khi mã hóa, tên của class sẽ bị thay đổi, khiến cho logic tìm class theo tên không hoạt động.
Tips
Để kiểm tra file APK sau khi mã hóa, bạn hãy sử dụng công cụ JADX – một công cụ Decompile APK rất là bá đạo.
Tổng kết
Ở bài viết này, mình đã giới thiệu cho các bạn những điều sau:
- Cách sử dụng trình mã hóa Proguard của Android Studio
- Kinh nghiệm khi mã hóa Proguard
- Công cụ Decompile APK và check mã hóa
Ở các bài viết sau mình sẽ chia sẻ sâu hơn về các dạng mã hóa khác nha.
Mọi ý kiến đóng góp rất mong các bạn sẽ comment ngay bên dưới bài viết này.
CHANGE LOGS:
- 11/06/2024: Update rules mới