1.Dex混淆原理

Dex文件中以类为核心,方法字段等数据都需要归属于某个类,所以在混淆时主要针对3类数据:

  • 类名
  • 类中的方法名
  • 类中的字段名

为了更好的理解Dex文件中的类,先让我们看看类数据之间的关系图:

confuse

对于每个类而言,都有一个class_def_item结构体,其中class_idx指明了这个类的类名,superclass_idx指明了这个类的父类,在这个class_def_item结构体中最重要的就是class_data_off这个字段,这个字段指出了这个类中所拥有的字段和方法,在混淆时需要先混淆类名,然后找到这个类所拥有的字段和方法进一步混淆。

2.混淆规则

并不是所有的类,方法和字段都能被混淆,在使用proguard混淆代码时同样需要进行一系列的设定,指出哪些可以被混淆,哪些不能被混淆,常用的混淆规则有:

  • Android系统组件(Activity,Service等)不能被混淆
  • 自定义view不能被混淆
  • jni调用不能被混淆
  • Android R文件不能被混淆
  • Android Parcelable,需要使用android序列化的不能被混淆
  • 枚举类型不能被混淆
  • 某些资源文件不能被混淆
  • 不能混淆init函数

由于混淆规则很多,要实现proguard那样的混淆器并不容易,本次实现代码中进行了简化,主要目的在理解混淆的原理。

3.关键代码

混淆之后需要重新计算Dex文件的头部中的signature和checksum,python代码如下:

生成固定长度的随机字符串:

在混淆类名是需要注意:类名中包含的包名不能被混淆,比如类名:

这时Lcom/example/util/ 这一段是不能被混淆,并且最后的;也不能被混淆,所以需要被混淆的数据只有Signature。实现时可以从字符串后面往前找到第一个/,混淆长度中再减去1(;长度) 。

在混淆方法名和字段名时没有混淆类名时的那种限制,直接进行混淆即可。

4.混淆效果

这里只混淆一个类中的方法和字段

混淆前:

hunxiao2

混淆后:

hunxiao0

可以看到该类的类名,类中字段和方法名都被混淆了。

5.完整代码

完整代码放在git上:https://github.com/cyg0810/DexConfuse

6.后记

这种方法混淆后的Dex虽然可以被正确读取,但是安装的时候会报” INSTALL_FAILED_DEXOPT ” 。具体原因将在下一篇文章中介绍。

 

 

观看更多有关 的文章?

*

    ty
    2015年12月4日

    你的源码中
    #print “len:”,strlen
    #读取不定长字符串
    classname = self.dex.read(strlen)
    这句有点不准确,因为一个汉字占用,2个字节,但是在size里面一个汉字只会算1。所以一个字节一个字节读取,读到00后停止会比较好。

      burningcodes
      2015年12月7日

      测试了一下的确有这个问题,之前没考虑中文的情况,非常感谢!

+
跳转到评论