zoukankan      html  css  js  c++  java
  • [Android_cracker] Android DEX安全攻防战

    一、DEX相关基础知识

         1、什么是DEX?
              DEX是Dalvik EXecutable的简称。
              打包.class文件为单一DEX文件并运行于Dalvik虚拟机。
              DEX文件打包进APK文件中(本质上是jar或zip文件)。
    http://img.blog.csdn.net/20130723221002593?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

              安装时,系统提取DEX文件进行检查和验证。
              第一次运行时,系统完成DEX优化,转换成odex文件。
              odex文件存放在/data/dalvik-cache目录并在执行时加载进内存执行。
    http://img.blog.csdn.net/20130723221750109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       
          2、DEX文件格式(查看更多内容请访问:http://blog.csdn.net/androidsecurity/article/details/8664778)

           http://img.blog.csdn.net/20130723222746531?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

         3、如何查看DEX文件
          目前有以下工具可以完成DEX文件的反编译。

        http://img.blog.csdn.net/20130723222537734?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

    二、攻击者隐藏软件行为的方法

           攻击者经常采用以下方式隐藏软件的行为:

         1、使用反射调用敏感API

               http://img.blog.csdn.net/20130725225910390?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

            该种方式能够使攻击者“隐藏”敏感API调用。但是这种方式只需要查看是否利用JAVA反射即可很容易的被识破。
            如果配合代码混淆技术,就会增加自动化识别的难度。对付这种“隐藏”方式,动态分析会更简单一些。

           2、代码逻辑“藏匿”在资源文件中

           可以通过修改文件后缀名隐藏代码逻辑 ,如下图:

    http://img.blog.csdn.net/20130725235517218?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast



            通过文件后缀隐藏可以通过file命令查看文件类型是否与后缀匹配很容易识别。
            我们还可以做的更加高级一点。下图将ELF可执行二进制文件附加在有效的图片文件中,通过file指令得到正确的文件类型,且该图片可以正常显示:

    http://img.blog.csdn.net/20130725235612750?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
              该种隐藏方式需要我们更加深入的查看所有的资源文件。看着是jpg图片文件,但并不一定全是(永远不要相信自己的眼睛)。
              也许还有其它更高级的隐藏恶意代码的方法。

         3、使用DexClassLoader动态加载技术

              可以使用Android DexClassLoader完成DEX的动态加载,DEX文件可以附属在assert或raw目录也可以运行时从网络下载。
           
    三、Android反逆向分析之旅

          我们可以利用逆向分析工具实现上的缺陷来触发其奔溃,从而达到反逆向分析的目的。

          Android反逆向分析的目标:
            Baksmali - 使用最广泛的DEX反编译工具 (apktool/antilvl等使用)(https://code.google.com/p/smali/)
            dex2jar - 可以把DEX反编译成jar的工具,然后通过JD-GUI查看。(http://code.google.com/p/dex2jar/)
            IDA Pro - (这个就不在介绍了吧!)(https://www.hex-rays.com/index.shtml)
            androguard - 也是比较流行的。(https://code.google.com/p/androguard/)

         1、构建DEX link section触发baksmali工具崩溃(DEX文件结构请查看http://blog.csdn.net/androidsecurity/article/details/8664778)

             由于baksmali工具不支持DEX文件的link section,所以我们可以构建DEX link section触发baksmali工具奔溃。如下图:

    http://img.blog.csdn.net/20130725235742796?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
            该方式常用于开发者阻止破解者逆向分析代码逻辑。 该方法已经被Lohan+ (AntiLVL) / jcase /和其它项目中使用。但是这种方式也有明显的缺点,可以根据异常信息很容易的修复分析工具。

          2、利用已知的JAR hack方法

              由于APK本质上就是zip/jar包,所以我们也可以利用已知的JAR hack方法。
              JAR对文件名的长度是没有现在的,但是操作系统要求文件名不能大于255;我们可以通过构建大于255字符的长类名来达到反逆向的目的。
              如何构建大于255的长类名呢?首先我们看一下DEX Class Def Item的格式:

           http://img.blog.csdn.net/20130808224444437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

           我们可以通过以下方式构建大于255的长类名:
               1、在源代码中添加大于255的字符串A。
               2、编译源代码,修改DEX文件头,修改Class descriptor_id为字符串A的String_idx

           下图是修改前后比较:

    http://img.blog.csdn.net/20130808224649343?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
      
      修改后的APK能够正常安装,如下图:

    http://img.blog.csdn.net/20130808224947250?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

      这种修改方法能够防止逆向分析,如下图:

    http://img.blog.csdn.net/20130808225047421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

       通过异常我们应该可以看出为什么大于255个字符会报错了吧。
       但是该种方式缺点是只能对付backsmali。 IDA、Dex2jar、Androguard仍然能够正常工作。
       该种方法易于检测和解决,当class名字长度>255要警惕该应用。
       
       3、插入无效字节码指令引发逆向工具崩溃

          由于大部分逆向工具都是线性读取字节码并解析,当遇到无效字节码时,就会引起反编译工具字节码解析失败。
          我们可以插入无效字节码到DEX文件,但要保证该无效字节码永远不会被执行(否则您的程序就会崩溃了!)。
      
    [java] view plaincopy
    1201 // Load 0 into v1  
    3801 0300 // A conditional jump which should always succeed, jumps over  
    // next bytes  
    FFFF // Bad opcodes  
           安装插入无效字节码的apk文件。如下图:

    http://img.blog.csdn.net/20130809001741093?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

            但是执行程序时,却报如下的错误:
      
      http://img.blog.csdn.net/20130809002006546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       运行的时候怎么会报错呢?
          Dalvik虚拟机并没有像我们预想的那样跳过无效的字节码,它会在执行之前验证所有调用序列上类的字节码是否有效。
       现在的问题是如何能够绕过Dalvik虚拟机的代码验证呢?
          我们如果插入无效代码在一个从来不会调用的类上不就可以绕过Dalvik运行时代码验证了吗!
       看如下插入后的运行结果:
    http://img.blog.csdn.net/20130810085818421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
         
       哈哈,成功运行了,接下来让我们看看该种方式反逆向的效果吧!
    http://img.blog.csdn.net/20130810090131953?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       
        (可惜的backsmali已经在版本2f81aec886d2修复了该bug,该方式已无效)

       http://img.blog.csdn.net/20130810090414312?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       Dex2jar 验证可行。
        
       http://img.blog.csdn.net/20130810090533406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       Androguard验证可行,(可惜的是Androguard很快修复了该bug)

    http://img.blog.csdn.net/20130810090802906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
        
       IDA验证未成功!

        http://img.blog.csdn.net/20130810090943015?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       ded工具验证成功!在你杀死该工具进程之前,它将一直运行在无效字节码所在类处理过程中。
     
       该种方法的缺点是很容易被工具修复。工具在反编译代码时,只要忽略会无效字节码的处理即可,backsmali、androgurad已经修复了该bug。
       该种方式和很容易被自动化监测,如果遇到无效代码就要警惕!
       逆向分析人员要尽量使用工具的最新版本。

       4、插入有效的字节码指令但后跟无效的数据引用

         插入无效的字节码指令目前工具已经可以正常工作,但是如果我们插入有效的字节码指令,但是后跟无效的数据引用,结果会是怎么样呢?
        
    [cpp] view plaincopy
    1201 // Load 0 into v1  
    3801 0300 // A conditional jump which should always succeed, jumps over  
    // next bytes  
    1a00 FF00 // Load const-string at index 255 (doesn’t exist)  
         这次我们仍然绕过Dalvik运行时字节码指令验证,但是我们替换“无效字节码指令”为合法字节码指令
    http://img.blog.csdn.net/20130810093016750?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
       
          backsmali验证成功!
    http://img.blog.csdn.net/20130810093113671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
          
         dex2jar验证成功!
    http://img.blog.csdn.net/20130810093236031?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
         
        Androguard验证成功,但是只会在反编译插入该“有效字节码指令”的方法报错。
    http://img.blog.csdn.net/20130810093647421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
        
        ded验证成功!

        http://img.blog.csdn.net/20130810093748437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
        IDA验证失败!

      该种方式也很容易被工具修复,逆向工具只要不盲目的解析一个不存在的索引即可。

       5、针对java反编译器缺陷进行攻击
      dex2jar+(JD-Gui或JAD) 组合工具是逆向分析经常使用的工具。dex2jar用于把DEX文件转换为java字节码JAR文件,JD-GUI或JAD用于把java字节码转化为java源代码。
      我们可以针对JAVA JD-Gui或JAD工具缺陷来达到反逆向分析的目的。达到的效果如下图所示:
    http://img.blog.csdn.net/20130810122804265?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

          6、针对backsmali对文件头处理缺陷
               我们刚才讲到baksmali在处理Link section的bug,还有类似的崩溃点吗?如图backsmali代码所示:
    http://img.blog.csdn.net/20130803142118765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

               当DEX Header size 不等于0x70时,backsmali也会抛出异常退出!
               Header_size 当前值正常情况下都等于0x70
    http://img.blog.csdn.net/20130803142436984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

       构建这种dex文件很容易实现。
       需要修复文件头每个表项的偏移量。
       修改后的Header size 等于0x78
    http://img.blog.csdn.net/20130803143224156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

       但是这种方式只能针对baksamli工具。且很工具很容易修复该bug。
       该方式也可以用于在DEX Header中隐藏数据和代码。
       我们可以在Dex文件头隐藏另一个DEX数据并在运行时加载附带DEX数据。
       构建非规范的Dex文件
    http://img.blog.csdn.net/20130728214717734?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

        通过反射调用DexFile类的方法加载附带DEX数据(android4.0以上才有我们需要的方     法http://blog.csdn.net/androidsecurity/article/details/9674251)

    http://img.blog.csdn.net/20130728215147468?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
      
      通过反射实际调用DexFile的openDexFile方法
    http://img.blog.csdn.net/20130803121206546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

     该种方式允许我们通过byte[]解析dex数据,而无须在再把DEX数据存储在设备的某个文件。
     我们可以从安装APK文件、内存或dalvik-cache等读取dex数据。
     打包好的DEX文件如下图所示:
    http://img.blog.csdn.net/20130803122316609?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZHNlY3VyaXR5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
     
        该种方式将给自动化分析工具带来一个问题,自动化工具会按照dex格式处理DEX文件而不会处理附带的dex数据。需要特定的工具、16进制编辑器或手工提取嵌入的dex数据。
     我们可以采用各种不同的方式增加嵌入数据的提取难度,比如:
        对嵌入的DEX数据进行加密;
        嵌入的DEX数据加密后在对其进行ZIP压缩;
        使用native代码解密,直接从内存加载;
        ......等等

        该种隐藏方式可以通过判断Dex文件头长度是否大于0x70检测。
     
        7、大端小端反转理论
            当前还没有Android逆向工具实现DEX文件端反转(也许IDA支持)。
            Dalvik虚拟机在DEX优化过程中会检测DEX端模式是否适合当前设备,如果不适合会反转DEX文件端模式。
            我们需要做的是变换DEX文件所有字节端结构,反转后的DEX文件可以中断逆向工具但是仍然可以在设备上运行。
            这种攻击方式理论上是可行的。我们可以参考Android源代码实现端的反转,具体代码位于/dalvik2/libdex/dexSwapAndVerify.cpp

    四、反虚拟机技术

         如何检测App运行环境是否为qemu虚拟机呢? 我们可以通过getprop获取相关信息,getprop在qemu虚拟机和移动设备上很多属性是不同的。比如:

     http://img.blog.csdn.net/20130725235326875?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

    getprop Android SDK中并没有公开接口,不过我们可以通过JAVA反射调用。
    http://img.blog.csdn.net/20130725235034453?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhemhpanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

    五、相关引用
    http://code.google.com/p/smali/
    http://code.google.com/p/androguard/
    http://code.google.com/p/dex2jar/
    http://siis.cse.psu.edu/ded/
    http://hex-rays.com/products/ida/index.shtml
    http://source.android.com/tech/dalvik/dex-format.html 

    英文原版:http://www.strazzere.com/papers/DexEducation-PracticingSafeDex.pdf
    该文章发表于Black Hat 2012,虽然内容不够新鲜,也许好多方法目前已经失效,但是仍然会给我们反逆向方面很多的启示!

  • 相关阅读:
    轻松搭建基于 SpringBoot + Vue 的 Web 商城应用
    Serverless 实战 —— Funcraft + OSS + ROS 进行 CI/CD
    急速搭建 Serverless AI 应用:为你写诗
    O'Reilly 1500 份问卷调研:2019 年 Serverless 落地到底香不香?
    2019 阿里巴巴云原生这一年
    快速部署 Spring PetClinic 到函数计算平台
    1354. Construct Target Array With Multiple Sums
    1352. Product of the Last K Numbers
    1351. Count Negative Numbers in a Sorted Matrix
    1347. Minimum Number of Steps to Make Two Strings Anagram
  • 原文地址:https://www.cnblogs.com/webapplee/p/4168542.html
Copyright © 2011-2022 走看看