您的位置:首页 > 编程语言

Andoird 混淆代码学习心得(上)

2016-03-17 10:10 176 查看

Andoird 混淆代码学习心得(上)

之前做Android混淆比较凌乱,基本都是在copy之前的配置,所以决定系统的整理下混淆打包的内容,深入理解下原理。

转载:http://blog.csdn.net/guolin_blog/article/details/50451259

1.混淆配置

在Android Studio当中混淆APK实在是太简单了,借助SDK中自带的Proguard工具,只需要修改build.gradle中的一行配置即可。可以看到,现在build.gradle中minifyEnabled的值是false,这里我们只需要把值改成true,打出来的APK包就会是混淆过的了。如下所示:

release {

minifyEnabled true

proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

}

其中minifyEnabled用于设置是否启用混淆,proguardFiles用于选定混淆配置文件。注意这里是在release闭包内进行配置的,因此只有打出正式版的APK才会进行混淆,Debug版的APK是不会混淆的。当然这也是非常合理的,因为Debug版的APK文件我们只会用来内部测试,不用担心被人破解。

那么现在我们来打一个正式版的APK文件,在Android Studio导航栏中点击Build->Generate Signed APK,然后选择签名文件并输入密码,如果没有签名文件就创建一个,最终点击Finish完成打包,生成的APK文件会自动存放在app目录下。除此之外也可以在build.gradle文件当中添加签名文件配置,然后通过gradlew assembleRelease来打出一个正式版的APK文件,这种方式APK文件会自动存放在app/build/outputs/apk目录下。

2.初步混淆的结果

(1).Acitivity 类名没有混淆的,onCreate()方法也没有被混淆,定义的方法、全局变量、局部变量都被混淆了(凡是需要在AndroidManifest.xml中去注册的所有类的类名以及从父类重写的方法名都自动不会被混淆。因此,除了Activity之外,这份规则同样也适用于Service、BroadcastReceiver和ContentProvider)

(2).工具类 类名没有被混淆,声明成native的方法也没有被混淆,但是非native方法的方法名和局部变量都被混淆了。

(3).Fragment 所有的方法名、全局变量、局部变量都被混淆了。

3.混淆默认配置

-dontusemixedcaseclassnames 表示混淆时不使用大小写混合类名。

-dontskipnonpubliclibraryclasses 表示不跳过library中的非public的类。

-verbose 表示打印混淆的详细信息。

-dontoptimize 表示不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。

-dontpreverify 表示不进行预校验。这个预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度。

-keepattributes Annotation 表示对注解中的参数进行保留。

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了。

-keepclassmembers class * implements android.os.Parcelable {

public static final android.os.Parcelable$Creator CREATOR;

}

表示不混淆Parcelable实现类中的CREATOR字段,毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。

-keepclassmembers class *.R$ {

public static ;

}

表示不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。

-dontwarn android.support.** 表示对android.support包下的代码不警告,因为support包中有很多代码都是在高版本中使用的,如果我们的项目指定的版本比较低在打包时就会给予警告。不过support包中所有的代码都在版本兼容性上做足了判断,因此不用担心代码会出问题,所以直接忽略警告就可以了。

4.proguard关键字

keep 保留类和类中的成员,防止它们被混淆或移除。

keepnames 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。

keepclassmembers 只保留类中的成员,防止它们被混淆或移除。

keepclassmembernames 只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。

keepclasseswithmembers 保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

keepclasseswithmembernames 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

5.proguard通配符

 匹配类中的所有字段

匹配类中的所有方法

匹配类中的所有构造函数

* 匹配任意长度字符,但不含包名分隔符(.)。比如说我们的完 整类名是com.example.test.MyActivity,使用com.,或者com.exmaple.都是无法匹配的,因为无法匹配包名中的分隔符,正确的匹配方式是com.exmaple..,或者com.exmaple.test.,这些都是可以的。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。

* 匹配任意长度字符,并且包含包名分隔符(.)。比如proguard-android.txt中使用的-dontwarn android.support.*就可以匹配android.support包下的所有内容,包括任意长度的子包。

* 匹配任意参数类型。比如void set*()就能匹配任意传入的参数类型,** get*()就能匹配任意返回值的类型。

… 匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: