Android代码混淆

作者: i小灰 | 来源:发表于2021-01-17 01:01 被阅读0次

最近在研究apk瘦身时,发现代码混淆有很大作用,所以就去简单研究了一下。

我认为,代码混淆可以保护核心功能不泄漏以及apk瘦身;但是也有个缺点:就是人为的可能会把不能混淆的代码混淆,导致crash。

经过整理发现代码混淆可以分为三部分:

  • 基本指令以及一些固定不混淆的代码;
  • 某些第三方包;
  • 自己书写的一些不要混淆的代码。
    注:其中第二部分,可以根据情况扩展或去掉某些未曾用到的指令;第三部分需要根据自己的情况去添加;

代码混淆

俗话说,授人以鱼不如授人以渔,但是先有鱼总是好的,所以接下来就会先介绍一下代码混淆的基本使用。

1. 开启混淆代码
在app module下的gradle文件中

android {
    ...
  
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

默认minifyEnable是false,我们只需要改为true就开启了混淆。这里只需要在release的时候开启混淆即可,代码混淆会加长APK的生成时间,而且android studio2.0以后使用instance run会停用ProGuard。

这时候打包,安装,如果引入了其他第三方的代码的话,不出意外时会crash的,虽然proguard-android.txt文件中已经包含了一些不混淆的指令了,那些事系统常规的指令,对于自定义的一些指令就需要自己在app下的proguard-rules.pro文件中去定义。
2. PROGUARD模板

proguard-rules.pro

我看这个库里边的内容也用分割线做了一下简单的分割,包含的也是上文说到的三部分,下面简单介绍一下具体包含的内容。

  • 基本指令:包含了压缩级别,忽略警告,混淆警告等;

  • 固定不混淆的代码:包含继承四大组件中的内容,support包,view相关、序列化相关、R文件、枚举、native方法等;

  • 第三方包:这一部分需要根据项目情况去处理,这里支持了我们公司常用框架里边的第三方包;

  • 自己书写的不需要混淆的代码:这里就需要根据自己的情况去书写了,而我们只需要知道哪些东西是不能混淆的就能编写了。
    下面来说一下,混淆的规则:

  • 第三方库。一般都会提供混淆规则,如果没有提供,报错后,我们就可以保护报错的类,不让其混淆,实在不行就用最暴力的解决办法,把其全部代码都不混淆。

  • 运行时动态改变代码。一般例如反射,实体类。

  • 被JNI中调用的类。

  • WebView中Js调用的方法。

  • View相关的类和事件。
    这两步过后,基本就完成了代码混淆,运行后发现问题再解决即可,下面就开始介绍一些混淆中的语法。

1、常用命令

命令 作用
-keep 防止该类所有内容被移除或重命名
-keepnames 防止类和成员被重命名
-keepclassmembers 防止成员被移除或者被重命名
-keepclasseswithmembers 防止拥有该成员的类和成员被移除或者被重命名
-keepclasseswithmembernames 防止拥有该成员的类和成员被重命名

2. 常用规则

  • 类:需要使用完全限定名;

  • *:通配符,任意字符串,不包含包名分隔符(.);

  • **:通配符,任意字符串,包含包名分隔符(.);

  • extends:继承某类的类;

  • implement:实现某接口的类;

  • $:内部类;

  • <init>:所有构造方法;

  • <fields>:所有成员变量;

  • <methods>:所有方法;

  • …:任意参数;

  • 修饰符:public private protected

3. 例子

含义 指令语句
不混淆某个类 -keep public class packageName.className{ *; }
不混淆某个包的所有类 -keep class packageName.**{ *; }
不混淆某个类的子类 -keep public class * extends packageName.className{ *; }
不混淆某个接口的子类 -keep public class * implements packageName.className{ *; }
不混淆某个类的构造方法 -keepclassmembers class packageName.className{ public <init style="box-sizing: border-box;">(); }</init>
不混淆某个类的某个方法 -keepclassmembers class packageName.className{ public void methodName(…); }
不混淆某个类的内部类 -keep class packageName.className$*{ *; }

混淆的步骤

上文中介绍了代码的混淆,其实Android的混淆中还包括了资源压缩,整个过程包括:压缩、优化、混淆、以及预校验,其中第四步在Android中可不要,默认是去掉了的,另外三个都是默认开启的。

  • 压缩:会移除未被使用的类和成员变量,会在优化后再次被执行;
  • 优化:在字节码级别执行优化,让应用运行的更快;
  • 混淆:增大反编译难度,类和类成员会被随机命名,除非用keep保护。
    下面再简单介绍一下再开启资源压缩,和开启代码混淆在一起加上shrinkResources true即可。但是这时候所有未被使用的资源都会被移除,但是有的资源我们可能是动态使用的,就需要保留。
    那么就可以创建一个包含标签的XML文件,并使用tools:keep属性指定保留的资源,使用tools:discard属性指定要删除的资源;多个就使用逗号隔开即可,还可以使用*通配符。例如:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2" />

对于资源的保留,还有一个严格应用的检查,开启后,在使用Resources.getIdentifier()就可以根据动态生成的字符串查询资源名字,例如:

String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());

使用方式也很简单,如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict" />

到这里,混淆相关的就基本上介绍完了,然后再总结一下需要注意的东西:

  • 一定要根据混淆规则判断自己的代码是否需要混淆;
  • 测试的版本一定需要打包后的apk;

还遗留的问题是:错误日志的定位问题?思路是根据输出的mapping文件去对应,没有详细的去落实,实际遇到了再补上具体的解决方案。

本文章参考文章

还遗留的问题是:错误日志的定位问题?思路是根据输出的mapping文件去对应,没有详细的去落实,实际遇到了再补上具体的解决方案。

参考

压缩代码和资源

写给Android开发者的混淆使用手册

Android Studio代码混淆插件

相关文章

  • ProGuard详解

    Android分享:代码混淆那些事Android代码混淆之混淆规则Android-Dev-Favorites An...

  • Android代码混淆

    待整理。。。 参考: Android混淆从入门到精通 Android代码混淆之混淆规则 代码混淆规则配置文件:pr...

  • Android混淆

    Android 代码混淆零基础入门

  • 你混淆Android代码多吗?

    ProGuard是一个开源的Java代码混淆器。它可以混淆Android项目里面的java代码,但是不能混淆资源,...

  • Android app代码混淆完整解决方案

    Android app代码混淆完整解决方案

  • Android代码混淆

    什么是代码混淆 删除无用代码,将代码中的各种元素,如包名、类名、函数名、变量名等改成无意义的符号,使得反编译你ap...

  • Android代码混淆

    作为Android开发者,如果你不想开源你的应用,那么在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使被...

  • Android 代码混淆

    代码混淆的作用代码混淆,就是把java文件在生成class文件是,类名,方法名等JAVA元素修改成没有意义的名称,...

  • Android 代码混淆

  • Android代码混淆

    keep 资源文件或者配置文件引用到的类(自定义View,四大组件等等) 反射类 模板

网友评论

    本文标题:Android代码混淆

    本文链接:https://www.haomeiwen.com/subject/quqoiktx.html