注意:本篇文章是本人阅读相关文章的总结,方便以后查阅,所有内容非原创,侵权删。
本篇文章内容来自于
1.Android高级进阶 顾浩鑫
2.相对应的知识块的最下方会给出原来的帖子的链接
前言
混淆是增加逆向工程和破解的难度,防止APP知识产权被窃取的一个有力手段。
Android混淆包括三种类型
1.Java代码的混淆
2.Native(C&C++)代码的混淆
3.资源文件的混淆
目录
- Java代码的混淆
--1.1 Proguard如何启用
--1.2 编写混淆文件
--1.3 Proguard生成的文件 - Native(C&C++)代码的混淆 NDK(待补)
- 资源文件的混淆(待补)
1. Java代码的混淆-Proguard
Java代码混淆一般依赖于Proguard或者DexGuard工具。其中Proguard免费开源,Proguard付费。DexGuard强大的多,但是一般情况下用DexGuard就足够了。
Android默认集成了ProGuard,它是一个免费的用于压缩、优化和混淆Java字节码的工具,混淆的功能主要是用简短的无意义的字母组合来对代码中的类、字段、方法和属性进行重命名,但它无法对字符串进行混淆。
即使用Proguard后,我们还是可以看到反编译后代码中完整的字符串定义。
我们可以选择商业版的Proguard-DexGuard。DexGuard对代码、资源、字符串、AndroidManifest.xml等进行了全面的加密和混淆。
Proguard的特性
Progurad不仅可代码混淆,还提供其他功能。主要有4个功能特性:
1.压缩:Proguard能通过分析字节码,能够检测并移除没有使用到的类、字段、方法和属性。
2.优化:优化java字节码,同时移除没有使用到的指令。
3.混淆:使用无意义的简短字母组合对类名、字段名和方法名进行重命名。
4.预检验:对上述处理后的代码进行预检验。
1.1 Proguard如何启用
在需要进行的module的build.gradle进行配置
android {
...
buildTypes {
release {
minifyEnabled true //用于指定是否对项目的代码进行混淆 true表示混淆 false表示不混淆
//proguardFiles用于指定混淆时使用的规则文件
//这里指定了2个 proguard-android.txt是AndroidSDK目录下的tools/proguard的,里面是所有项目通用的混淆规则
//proguard-rules.pro是当前项目根目录下的,里面可以编写当前项目特有的混淆规则
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
...
}
1.2 编写混淆文件
1.2.1 proguard-android.txt 默认混淆配置文件
proguard-android.txt位于AndroidSDK目录/tools/proguard,该文件是Proguard的基本配置,几乎是每个APP都要用到的配置。
1.2.2 proguard-rules.pro 文件的编写
proguard-android.txt 默认混淆配置文件的配置是远远不够的,我们需要根据自身APP的特殊性增加或减少相关的配置。
混淆文件的规则大致分为三种类型
- 公共的混淆规则:每个APP都适用,主要是针对Proguard的基本配置,以及Android SDK中API设置的规则,例如Activity、Parceable等。
- APP特有的混淆规则:根据APP自身的特点进行设置,例如某些类会被反射调用,如果被混淆,那么反射就找不到了。
- 第三方函数库或者SDK的混淆规则:如果APP引入了第三方开源函数库或者SDK,那么需要查看这些函数库或者SDK的使用说明,将需要去混淆的地方加上去。
混淆模版:(具体查看5分钟搞定android混淆)
#-------------------------------------------定制化区域----------------------------------------------
#---------------------------------1.实体类---------------------------------
#-------------------------------------------------------------------------
#---------------------------------2.第三方包-------------------------------
#-------------------------------------------------------------------------
#---------------------------------3.与js互相调用的类------------------------
#-------------------------------------------------------------------------
#---------------------------------4.反射相关的类和方法-----------------------
#----------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
#-------------------------------------------基本不用动区域--------------------------------------------
#---------------------------------基本指令区----------------------------------
-optimizationpasses 5
-dontskipnonpubliclibraryclassmembers
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
#----------------------------------------------------------------------------
#---------------------------------默认保留区---------------------------------
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-keep class android.support.** {*;}
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
}
-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 **.R$* {
*;
}
-keepclassmembers class * {
void *(**On*Event);
}
#----------------------------------------------------------------------------
#---------------------------------webview------------------------------------
-keepclassmembers class fqcn.of.javascript.interface.for.Webview {
public *;
}
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, jav.lang.String);
}
#----------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
1.3 Proguard生成的文件
在AS中使用Proguard对代码进行混淆,会在build/outputs/mapping/release目录下生成四个文件。
1.dump.txt:列出生成的APK文件中所有class文件的内部结构。
2.mapping.txt:列出混淆前的java源码和混淆后的类、方法和属性名字之间的映射。
3.seeds.txt:列出为混淆的类和成员
4.usage.txt:列出从apk文件中剥离的代码
2.Native(C&C++)代码的混淆 NDK(待补)
Android开发中经常需要在客户端中保存敏感信息,相比较将敏感信息写在Java层,将其下移到NDK层是更好的选择。
虽然NDK层存储敏感信息安全性好,但仍然避免不了被破解,为了进一步增加破解难度,我们需要对NDK层的代码进行混淆保护。
Native 层代码混淆没有一个标准的方案或者函数库,常见且比较简单的方法是使用花指令,使Native代码在被反汇编时出错,从而让破解者无法清晰正确的反汇编出代码的内容。
参考
1.Obfuscator-LLVM
2.直接使用由Ryan Welton预先编译的包,具体参见ANdroidObfuscation-NDK这个例子。
3.资源文件的混淆(待补)
资源文件的混淆也没有统一的方案,但是并不常对资源文件进行混淆,因为资源文件的保密性美欧那么高,破解者可以通过apktool轻松得到。
资源文件混淆的好处:
1.提高APP破解的难度
2.减少APP的最终包的大小:资源文件的混淆类似于java代码的混淆,也是通过使用无意义的字母来代替完整的命名实现的。他的一个副作用是能在一定程度上减少APP的大小。
资源文件的混淆方案目前有美团和微信两种。
1⃣️美团是通过修改AAPT在处理资源文件相关的源码达到资源文件名的替换。
查看美团Android资源混淆保护实践
2⃣️微信是通过直接修改resources.arsc文件达到资源文件名的混淆。
查看安装包立减1M--微信Android资源混淆打包工具
微信方案开源,地址在AndResGuard