zoukankan      html  css  js  c++  java
  • Android程序的反编译对抗研究

    转自: http://www.freebuf.com/tools/76884.html

    一、前言

    对抗反编译是指让apk文件或者dex文件无法正常通过反编译工具,而且有可能导致工具异常或者崩溃,如apktool、baksmali、dex2jar、JEB等等工具,如下图dex2jar无法正常工作。

    二、Dex文件格式解析

    目前大多数android软件的反编译工具都是开源的,比如apktool、Dex2jar、baksamli,大家可以非常方便的从github下载并源阅读代码,然后找到可以利用的点,再在自己的软件中加入干扰代码,让反编译工具出现异常或者无法正常阅读代码。

    接下来让我们先来熟悉一下dex文件格式 ,一个dex文件由以下几个部份组成:

    1.     Dex Header:    Dex结构头它指定了dex文件的一些基本属性,并记录了部份数据表在dex文件中的物理偏移。
    2.     String Table:  字符串表,存储字符串的索引和个数
    3.     Type Table:   类型表,存储类型的索引和个数
    4.     Proto Table:  函数元型表,存储函数元型索引和个数
    5.     Field Table:  字段表,存储字段索引和个数
    6.     Method Table:  方法表,存储方法索引和个数
    7.     Class def Table:类定义表,存储类定义索引和个数
    8.     Data Section:  存储数据,由以上类型的索引查找

    有兴趣的可以直接翻看android的源码或者参考以下链接:

    http://www.netmite.com/android/mydroid/dalvik/docs/dex-format.html

    既然要在代码中添加干扰指令,接下的DexClassDef结构,肯定是要了解的非常清楚。

    结构中包含了类的类型偏移、访问标志、父类类型索引、接口偏移、注释、静态类型的偏移信息,整体结构图定义如下:

    struct DexClassDef
    {  
       u4 classIdx    
       u4 accessFlags
       u4 superclassIdx 
       u4 interfacesOff  
       u4 sourcefileIdx 
       u4 annotationsOff  
       u4 classDataOff    
       u4 staticValuesOff
    }

    DexClassDef结构字段详细说明:

    classIdx    字段是一个索引值,类的类型,做为下标索引在DexTypeID结构列表中查找
    accessFlags   字段是类的访问标志,以ACC_开头的枚举值
    superclassIdx  字段是父类的类型,做为下标索引在DexTypeID结构列表中查找
    interfacesOff  字段是接口类型,做为下标索引在DexTypeList结构列表中查找
    sourcefileIdx  字段是源文件名,做为下标索引在DexTypeList结构列表中查找
    annotationsOff 字段是注释信息的偏移,指向DexAnnotationsDirectoryItem结构
    classdataOff  字段是指向了DexClassData结构体的偏移
    staticValuesOff 字段是指向DexEncodeArray结构体的偏移,记录静态数据的信息

    DexClassData结构说明:

    struct DexClassData
    {
       DexClassDataHeader header;
       DexField*  staticFields     //静态字段,DexField结构
       DexField*  instanceFields   //实例字段,DexField结构
       DexMethod* directMethods    //直接方法,DexMethod结构
       DexMethod* virtualMethods   //虚方法,  DexMethod结构
    }

    DexClassData结构中的DexMethod类型描述了:方法的原型、名称、访问标志以及代码数据块,codeOff字段指向了一个DexCode结构,它描述了方法更详细的信息以及方法中指令的内容。

    DexMethod结构声明如下

    struct DexMethod
    {  
    u4 methodIdx  //指向DexMethodId的索引
       u4 accessFlags//访问标志
    u4 codeOff    //指向dexCode的结构偏移
    }
    struct DexCode
    {
      ushort  registerSsize//使用的寄存器的数目
      ushort  insSize      //传入参数的数目
      unshort outsSize     //调用其他方法时使用的寄存器个数
      unshort triesSize    //try/catch异常块个数
      uint    debugInfoOff //调试信息的偏移
      uint    insnsSize    //指令集个数
      ushort  insns[1];     //指令集数组,变长数组
    }

    DexClassData树型结构图:

    三、调试dex2jar工程

    1. 将dex2jar源码导入IntelliJ IDEA,导入后IntelliJ IDEA会自动查找对应 Grable并下载,需要比较长的时间等待

    源码地址: https://github.com/pxb1988/dex2jar

    2.  选中Grable中的dex2jar/dex2jar/Tasks/other/antlr2java进行编译 

    3. 点击工具栏的 Project Structure, 然后选择Modules -> d2j-smali -> build,然后点击Excluded

    4. 选择 build/generated-sources/antlr, 然后点击 Sources

    5. 最后打开Excluded Gradle Task弹出对话框,运行clean distZip 命令

    执行完Gradl clean distZip命令后会在dex2jar-2.xdex-toolsuilddistributions目录下生成 dex-tools-2.1-SNAPSHOT.zip,压缩包内是编译完后生成的jar文件和一些配置信息文件。大家请参考dex2jar.sh文件,它向我们说明需要使用lib目录下的所有jar文件和入口函数com.googlecode.dex2jar.tools.Dex2jarCmd 才能将dex文件转换成jar文件

    6.将dex文件转换成jar文件需要执行转换命令

    格式如下:

    java -Xms512m -Xmx1024m -classpath  .lib*.jar com.googlecode.dex2jar.tools.Dex2jarCmd classdex.dex

    根据以上的命令,来配置调试参数,设置如下:

    7.设置完成后,就可以开始调试

    四、dex2jar反编译失败原因分析

    1.首先我们从解包失败的错误异常入手,定位崩溃处的代码。

    通过错误提示可以定位到dex2jar崩溃处的代码,源码位置如下:

    dex-irsrcmainjavacomgooglecodedex2jarirTypeClass.java

    2. 在崩溃的函数处下断点,开始调试。

    a)通过抛出的异常的说明“cant not merge I and Z”,以及整个调用堆栈。

    我们可以看出造成这个异常的原因是函数调用时,实参的类型和形参类型不匹配引起的。因为在Java语法中,将实参是布尔类型传递给形参是int类型。这样是不合法的,所以导致dex2jar在检查的参数类型的时候失败。

    b)知道了崩溃的原因,那我们就需要确定它具体是使用怎样的方法做到的,通过dex2jar生成的error异常信息详细说明文件得知该dex文件中的每一个函数头部都加了一句这样的代码Exit.b(Exit.a())请看Ida,现在大致能猜到混淆者所做的工作:

    1.首先解析dex文件格式,定位到DexCode结构中的insns成员

    2.向代码中添加一个类成员对象名字叫Exit,然后添加代码Exit.b(Exit.a())

    3.明白了怎么添加干扰代码,接下来分析一下dex2jar的工作流程,dex2jar转换成jar文件这个过程中会验证,函数调用时的形参和实参的合法性,请看下图,解析到INVOKE_开头的指令时,会开始解析返回值,供给参数,和实参等信息,具体逻辑和代码大家有兴趣可以详细地研究一下dex2jar源码。

    4.merge负责的工作是参数类型的验证,如果两个类型相同,返回形参的类型,形参为UNKONW返回实参,实参为UNKONW返回形参,两个类型都不相同,则匹配异常

    5.最后在dex2jar里添加代码,使dex文件能正确的被反编译成功。这里给出一段可以成功让dex2jar反编译的出jar文件的代码(其实方法有很多)

    下图是成功反编译的jar文件

  • 相关阅读:
    YII2操作mongodb笔记(转)
    MongoDB创建数据库和集合命令db.createCollection详解(转)
    MongoDB设置访问权限、设置用户(转)
    使用Robomongo 连接MongoDB 3.x 报 Authorization failed 解决办法(转)
    Yii2框架与MongoDB拓展、Redis拓展的安装流程
    YII2 Model 类切换数据库连接
    Centos6.5搭建java开发环境
    YII切换开发和生产环境(命令)
    YII2 实现后台操作记录日志(转)
    phpstorm2018激活方法--使用激活码
  • 原文地址:https://www.cnblogs.com/jhj117/p/4864495.html
Copyright © 2011-2022 走看看