Android代码混淆

代码混淆

如有错误可以QQ邮箱联系,745661590@qq.com
github不支持脚注

代码混淆概念[1]

代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种功能各异的代码混淆器。

混淆配置

我们一般直接在app的build.gradle文件中设置minifyEnabled true即可;
我们一般也加上shrinkResources true,打开资源压缩。用shrinkResources true开启资源压缩后,所有未被使用的资源默认被移除。

android {
    buildTypes {
        release {
            minifyEnabled true//是否启动混淆true:打开;false:关闭
            shrinkResources true//打开资源压缩。
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

设置白名单

白名单也就是proguard-rules.pro中我们自定义哪些不添加混淆。

关键字[2]

关键字 描述
dontwarn dontwarn是一个和keep可以说是形影不离,尤其是处理引入的library时.
keep 保留类和类中的成员,防止被混淆或移除
keepnames 保留类和类中的成员,防止被混淆,成员没有被引用会被移除
keepclassmembers 只保留类中的成员,防止被混淆或移除
keepclassmembernames 只保留类中的成员,防止被混淆,成员没有引用会被移除
keepclasseswithmembers 保留类和类中的成员,防止被混淆或移除,保留指明的成员
keepclasseswithmembernames 保留类和类中的成员,防止被混淆,保留指明的成员,成员没有引用会被移除
[保持命令] [类] {
    [成员] 
}

通配符

去除反斜杠,markDown中我不知道怎么去除

通配符 描述
* 匹配任意长度字符,不包含包名分隔符(.)
** 匹配任意长度字符,包含包名分隔符(.)
*** 匹配任意参数类型
$ 内部类
<\init> 匹配类中所有的构造函数
<\fields> 匹配类中的所有字段
<\method> 匹配类中所有的方法
匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。
extends 即可以指定类的基类
implement 匹配实现了某接口的类

规则使用

  • 不混淆某个类

    -keep public class com.dongdongwu.thor.entry.Test { *; }
    
  • 不混淆某个包所有的类

    -keep class com.dongdongwu.thor.entry.** { *; }
    
  • 不混淆某个类的子类

    -keep public class * extends com.dongdongwu.thor.entry.Test { *; }
    
  • 不混淆所有类名中包含了“model”的类及其成员

    -keep public class **.*model*.** { *; }
    
  • 不混淆某个接口的实现

    -keep class * implements com.dongdongwu.thor.entry.Test { *; }
    
  • 不混淆某个类的构造方法

    -keepclassmembers class com.dongdongwu.thor.entry.Test {
        public <init>(); 
    }
    
  • 不混淆某个类的特定的方法

    -keepclassmembers class com.dongdongwu.thor.entry.Test {
        public void test(java.lang.String); 
    }
    
  • 不混淆某个类的内部类

    -keep class com.dongdongwu.thor.entry.Test$* {
        *; 
    }
    

我总结的

最新的proguard-android.txt中添加了很多下面已经有的,再添加的时候看看是不是已经有了


#######################-----app中-----############################
#如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆

#######################-----第三方-----############################

#######################-----WebView(项目中没有可以忽略)-----############################
#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);
}
#在app中与HTML5的JavaScript的交互进行特殊处理
#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理:
-keepclassmembers class com.ljd.example.JSInterface {
    <methods>;
}


#######################-----其他-----############################
# 删除代码中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(...);
}

# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

#######################-----基本-----############################
#指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)
-optimizationpasses 5

#混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名,混淆后类名都为小写)
-dontusemixedcaseclassnames

#指定不去忽略非公共的库的类
#默认跳过,有些情况下编写的代码与类库中的类在同一个包下,并且持有包中内容的引用,此时就需要加入此条声明
-dontskipnonpubliclibraryclasses
#指定不去忽略非公共的库的类的成员
-dontskipnonpubliclibraryclassmembers

#Optimization is turned off by default. Dex does not like code run
#hrough the ProGuard optimize and preverify steps (and performs some
#of these optimizations on its own).
#不进行优化,建议使用此选项,不优化输入的类文件(原因见上边的原英文注释)
-dontoptimize
#不做预检验,preverify是proguard的四个步骤之一
#Android不需要preverify,去掉这一步可以加快混淆速度
-dontpreverify

#屏蔽警告
-ignorewarnings

#指定混淆是采用的算法,后面的参数是一个过滤器
#这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#避免混淆Annotation、内部类、泛型、匿名类
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod

#表示不混淆声明的两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

#抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
#重命名抛出异常时的文件名称,点击鼠标可以到达错误文件位置
-renamesourcefileattribute SourceFile

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

#不混淆R文件中的所有静态字段,以保证正确找到每个资源的id
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
#保留四大组件,自定义的Application等这些类不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-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

#处理support包
-keep class android.support.** {*;}
-dontnote android.support.**
-dontwarn android.support.**

#保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

#保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

#保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

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

#保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

#see http://proguard.sourceforge.net/manual/examples.html#beans
#不混淆View中的setXxx()和getXxx()方法,以保证属性动画正常工作
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#不混淆Activity中参数是View的方法,例如,一个控件通过android:onClick="clickMethodName"绑定点击事件,混淆后会导致点击事件失效
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

#保留Keep注解的类名和方法(最新的proguard-android.txt中包括了这个)
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

#第三方jar包不被混淆
-keep class com.github.** {*;}

参考文档


  1. 摘抄自百度百科-代码混淆

  2. 摘抄自Android混淆的关键字描述

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • 什么是代码混淆 代码混淆就是将代码中的各种元素,如变量,方法,类和包的名字改写成无意义的名字,增加项目反编译后被读...
    蜗牛家族史阅读 5,144评论 1 4
  • 混淆是对自己劳动成果的一种保护 今天就总结一下 我最近这段时间的使用心得 在这里做下记录(以AS举例说明) 首先...
    nade_s阅读 373评论 0 1
  • 本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路。请大家不要再走回头路,可能...
    Zane_Samuel阅读 55,355评论 8 93
  • 最近抽空研究了下android 加壳技术,发现关于加壳的源代码特别少,即使有也不能做到版本兼容,问题又特别多,对a...
    悠悠我思阅读 1,639评论 0 3
  • 文章转自我个人博客 本文前半部分对照 Proguard 文档 (Manul 中的 Introduce 部分)进行翻...
    搬代码白言午阅读 2,204评论 1 5