Android 实现代码混淆的实例
Android实现代码混淆的实例
1、简介
代码混淆(Obfuscatedcode)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。
混淆的目的是为了加大反编译的成本,但是并不能彻底防止反编译。
2、如何开启混淆
通常我们需要找到项目路径下app目录下的build.gradle文件,找到minifyEnabled这个配置,然后设置为true即可,如下:
release{ minifyEnabledtrue proguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro' }
3、proguard又是什么呢
这是java官网给出的定义:
ProGuardisafreeJavaClassfileshrinker,optimizer,obfuscator, andpreverifier.Itdetectsandremovesunusedclasses,fields,methods, andattributes.Itoptimizesbytecodeandremovesunusedinstructions. Itrenamestheremainingclasses,fields,andmethodsusingshortmeaninglessnames. Finally,itpreverifiestheprocessedcodeforJava6orhigher,orforJavaMicroEdition.
作用:
- proguard是一个集文件压缩,优化,混淆和校验等功能的工具
- 检测并删除无用的类,变量,方法和属性
- 优化字节码并删除无用的指令
- 通过将类名,变量名和方法名重命名为无意义的名称实现混淆效果
- 还校验处理后的代码
4、常见语句
-optimizationpasses5
代码混淆压缩笔记,在0~7之间
-dontusemixedcaseclassnames
混淆后类名都小写
-dontskipnonpubliclibraryclasses
不去忽略非公共的库的类
-dontskipnonpubliclibraryclassmembers
不去忽略非公共的库的类的成员
-dontpreverify
不做预校验的操作
-verbose -printmappingproguardMapping.txt
生成原类名和混淆后的类名的映射文件
-optimizations!code/simplification/cast,!field/*,!class/merging/*
指定混淆时采用的算法
-keepattributes*Annotation*,InnerClasses
注解不混淆
-keepattributesSignature
泛型不混淆
-keepattributesSourceFile,LineNumberTable
抛出异常时保留代码行号
用的最多的指令
-keepclassXXXX
保留类名不变,也就是类名不混淆,而类中的成员名不保证。当然也可以是继承XXX类的所有类名不混淆
-keepclasseswithmembersclassXXXX
保留类名和成员名,当然也可以是类中特定方法
5、哪些不混淆
- 反射中使用的元素
- 与网络请求相关实体类
- 使用注解的元素
- 四大组件
- WebView中与JS交互的类
- 枚举等
6、混淆文件编写
按照以上的规则和基本语句,我们将混淆文件分为两个区域:
定制化区域:分为实体类、第三方、js相关、反射相关,应按项目真实情况进行编写,具体会在稍后提到;
基本不动区直接复制即可。
#-------------------------------------------定制化区域---------------------------------------------- #---------------------------------1.实体类--------------------------------- #---------------------------------2.第三方包------------------------------- #---------------------------------3.与js互相调用的类------------------------ #---------------------------------4.反射相关的类和方法----------------------- #-------------------------------------------基本不用动区域-------------------------------------------- #---------------------------------基本指令区---------------------------------- -optimizationpasses5 -dontskipnonpubliclibraryclassmembers -printmappingproguardMapping.txt -optimizations!code/simplification/cast,!field/*,!class/merging/* -keepattributes*Annotation*,InnerClasses -keepattributesSignature -keepattributesSourceFile,LineNumberTable #---------------------------------------------------------------------------- #---------------------------------默认保留区--------------------------------- -keeppublicclass*extendsandroid.app.Activity -keeppublicclass*extendsandroid.app.Application -keeppublicclass*extendsandroid.app.Service -keeppublicclass*extendsandroid.content.BroadcastReceiver -keeppublicclass*extendsandroid.content.ContentProvider -keeppublicclass*extendsandroid.app.backup.BackupAgentHelper -keeppublicclass*extendsandroid.preference.Preference -keeppublicclass*extendsandroid.view.View -keeppublicclasscom.android.vending.licensing.ILicensingService -keepclassandroid.support.**{*;} -keeppublicclass*extendsandroid.view.View{ ***get*(); voidset*(***); public(android.content.Context); public (android.content.Context,android.util.AttributeSet); public (android.content.Context,android.util.AttributeSet,int); } -keepclasseswithmembersclass*{ public (android.content.Context,android.util.AttributeSet); public (android.content.Context,android.util.AttributeSet,int); } -keepclassmembersclass*implementsjava.io.Serializable{ staticfinallongserialVersionUID; privatestaticfinaljava.io.ObjectStreamField[]serialPersistentFields; privatevoidwriteObject(java.io.ObjectOutputStream); privatevoidreadObject(java.io.ObjectInputStream); java.lang.ObjectwriteReplace(); java.lang.ObjectreadResolve(); } -keepclass**.R$*{ *; } -keepclassmembersclass*{ void*(**On*Event); } #---------------------------------webview------------------------------------ -keepclassmembersclassfqcn.of.javascript.interface.for.Webview{ public*; } -keepclassmembersclass*extendsandroid.webkit.WebViewClient{ publicvoid*(android.webkit.WebView,java.lang.String,android.graphics.Bitmap); publicboolean*(android.webkit.WebView,java.lang.String); } -keepclassmembersclass*extendsandroid.webkit.WebViewClient{ publicvoid*(android.webkit.WebView,jav.lang.String); } #------------------------------------------------------------------------------------
实体类:
-keepclass你的实体类所在的包.*{;}
实体类由于涉及到与服务端的交互,各种gson的交互如此等等,是要保留的。将你项目中实体类都挑出来,用以上语法进行保留。
如果实体类都在同一一个包下,就和上面一样,很简单;如果实体类分布在各个包下,不好意思,挨个添加。
第三方包
需到项目的build.gradle文件中找到所有添的依赖,然后去官网或者github找到对应的混淆代码,添加到我们自己的混淆文件中。
如果是添的jar包的话,就像如下来写
#log4j -libraryjarslog4j-1.2.17.jar -dontwarnorg.apache.log4j.** -keepclassorg.apache.log4j.**{*;}
大致意思就是不混淆,不报warn。如果gradle报错的话,可以考虑注释掉-libraryjarslog4j-1.2.17.jar这句。
与JS交互相关
如果没有可跳过
-keepclass你的类所在的包.**{*;}
如果是内部类的话这样写:
-keepclasseswithmembersclass你的类所在的包.父类$子类{;}
反射相关
没有可跳过
-keepclass你的类所在的包.**{*;}
ok,这样就可以了,其实混淆很简单!
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!