Apk的混淆,这里的混淆分为两种代码混淆和资源文件混淆或是通过第三方加固

Android提供了Progurd方式来混淆apk中的代码,其核心的逻辑是在代码层将一些易懂的源代码类名,方法名称替换成毫无意义的a、b、c、d…,这样当别人反编译出你的Apk文件时,看到的源代码也无法还原其本身的逻辑。

  1. proguard混淆语法

-libraryjars class_path 应用的依赖包,如Android-support-v4  
-keep [,modifier,...] class_specification 这里的keep就是保持的意思,意味着不混淆某些类
-keepclassmembers [,modifier,...] class_specification 同样的保持,不混淆类的成员  
-keepclasseswithmembers [,modifier,...] class_specification 不混淆类及其成员  
-keepnames class_specification 不混淆类及其成员名  
-keepclassmembernames class_specification 不混淆类的成员名  
-keepclasseswithmembernames class_specification 不混淆类及其成员名  
-assumenosideeffects class_specification 假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等  
-dontwarn [class_filter] 不提示warnning 

  1. 混淆原则
jni方法不可混淆
反射用到的类不混淆(否则反射可能出现问题)
AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆
Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常
使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
有用到WEBView的JS调用也需要保证写的接口方法不混淆

2.第三方库的混淆原则

一般的第三方库都有自身的混淆方案,可直接引用其自身的混淆配置即可
若无混淆配置,一般的可配置不混淆第三方库


1.代码混淆-Progurd

1.1)在Android studio的Android项目中找到module的gradle配置文件,添加proguard配置

1. 修改module下的build.gradle
        buildTypes {
            release {
                // 是否进行混淆
                minifyEnabled true
                // 混淆文件的位置
                // proguard是一个压缩、优化和混淆Java字节码文件的免费的工具
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    2. 在proguard-rules.pro中添加:
        #指定代码的压缩级别
        -optimizationpasses 5

        #包明不混合大小写
        -dontusemixedcaseclassnames

        #不去忽略非公共的库类
        -dontskipnonpubliclibraryclasses

         #优化  不优化输入的类文件
        -dontoptimize

         #预校验
        -dontpreverify

         #混淆时是否记录日志
        -verbose

         # 混淆时所采用的算法
        -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

        #保护注解
        -keepattributes *Annotation*

        # 保持哪些类不被混淆
        -keep public class * extends android.app.Fragment
        -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
        #如果有引用v4包可以添加下面这行
        -keep public class * extends android.support.v4.app.Fragment



        #忽略警告
        -ignorewarning

        ##记录生成的日志数据,gradle build时在本项目根目录输出##

        #apk 包内所有 class 的内部结构
        -dump class_files.txt
        #未混淆的类和成员
        -printseeds seeds.txt
        #列出从 apk 中删除的代码
        -printusage unused.txt
        #混淆前后的映射
        -printmapping mapping.txt

        ########记录生成的日志数据,gradle build时 在本项目根目录输出-end######


        #####混淆保护自己项目的部分代码以及引用的第三方jar包library#######

        #-libraryjars libs/umeng-analytics-v5.2.4.jar

        #三星应用市场需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar
        #-libraryjars libs/sdk-v1.0.0.jar
        #-libraryjars libs/look-v1.0.1.jar

        #如果不想混淆 keep 掉
        -keep class com.lippi.recorder.iirfilterdesigner.** {*; }
        #友盟
        -keep class com.umeng.**{*;}
        #项目特殊处理代码

        #忽略警告
        -dontwarn com.lippi.recorder.utils**
        #保留一个完整的包
        -keep class com.lippi.recorder.utils.** {
            *;
         }

        -keep class  com.lippi.recorder.utils.AudioRecorder{*;}


        #如果引用了v4或者v7包
        -dontwarn android.support.**

        ####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####

        -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*(...);
        }

        #保持 native 方法不被混淆
        -keepclasseswithmembernames class * {
            native ;
        }

        #保持自定义控件类不被混淆
        -keepclasseswithmembers class * {
            public (android.content.Context, android.util.AttributeSet);
        }

        #保持自定义控件类不被混淆
        -keepclassmembers class * extends android.app.Activity {
           public void *(android.view.View);
        }

        #保持 Parcelable 不被混淆
        -keep class * implements android.os.Parcelable {
          public static final android.os.Parcelable$Creator *;
        }

        #保持 Serializable 不被混淆
        -keepnames class * implements java.io.Serializable

        #保持 Serializable 不被混淆并且enum 类也不被混淆
        -keepclassmembers class * implements java.io.Serializable {
            static final long serialVersionUID;
            private static final java.io.ObjectStreamField[] serialPersistentFields;
            !static !transient ;
            !private ;
            !private ;
            private void writeObject(java.io.ObjectOutputStream);
            private void readObject(java.io.ObjectInputStream);
            java.lang.Object writeReplace();
            java.lang.Object readResolve();
        }

        #保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
        #-keepclassmembers enum * {
        #  public static **[] values();
        #  public static ** valueOf(java.lang.String);
        #}

        -keepclassmembers class * {
            public void *ButtonClicked(android.view.View);
        }

        #不混淆资源类
        -keepclassmembers class **.R$* {
            public static ;
        }

        #避免混淆泛型 如果混淆报错建议关掉
        #–keepattributes Signature

        #移除log 测试了下没有用还是建议自己定义一个开关控制是否输出日志
        #-assumenosideeffects class android.util.Log {
        #    public static boolean isLoggable(java.lang.String, int);
        #    public static int v(...);
        #    public static int i(...);
        #    public static int w(...);
        #    public static int d(...);
        #    public static int e(...);
        #}

        #如果用用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错。
        #gson
        #-libraryjars libs/gson-2.2.2.jar
        -keepattributes Signature
        # Gson specific classes
        -keep class sun.misc.Unsafe { *; }
        # Application classes that will be serialized/deserialized over Gson
        -keep class com.google.gson.examples.android.model.** { *; }

方案一:最简单的方法,我们按照Proguard的做法,直接在源码级别修改,将代码以及xml的R.string.name中替换到R.string.a,icon.png重命名为a.png 然后再交给Android编译。

方案二:根据Android的编译流程,所有资源ID已经被编译成32位int值。这说明我们并不需要去修改xml与Java,因为在编译过程已经被R.java所替换,我们直接修改resources.arsc的二进制数据,不改变打包流程,只要在生成resources.arsc之后修改它,同时重命名资源文件。

方案三:直接处理安装包. 不依赖源码,不依赖编译过程,仅仅输入一个安装包,得到一个混淆包。

第三方加固:

1 使用梆梆加固和爱加密加固apk




你可能感兴趣的:(Android,核心技术)