本文章由Jack_Jia编写,转载请注明出处。
文章链接: http://blog.csdn.net/jiazhijun/article/details/9428861

作者:Jack_Jia 邮箱:309zhijun@163.com


英文原版:http://www.strazzere.com/papers/DexEducation-PracticingSafeDex.pdf

该文章发表于Black Hat 2012,虽然内容不够新鲜,也许好多方法目前已经失效,但是仍然会给我们反逆向方面很多的启示!


一、DEX相关基础知识


1、什么是DEX?

DEX是Dalvik EXecutable的简称。

打包.class文件为单一DEX文件并运行于Dalvik虚拟机。

DEX文件打包进APK文件中(本质上是jar或zip文件)。


安装时,系统提取DEX文件进行检查和验证。

第一次运行时,系统完成DEX优化,转换成odex文件。

odex文件存放在/data/dalvik-cache目录并在执行时加载进内存执行。


2、DEX文件格式(查看更多内容请访问:http://blog.csdn.net/androidsecurity/article/details/8664778)



3、如何查看DEX文件

目前有以下工具可以完成DEX文件的反编译。



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


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


1、使用反射调用敏感API



该种方式能够使攻击者“隐藏”敏感API调用。但是这种方式只需要查看是否利用JAVA反射即可很容易的被识破。

如果配合代码混淆技术,就会增加自动化识别的难度。对付这种“隐藏”方式,动态分析会更简单一些。


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


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




通过文件后缀隐藏可以通过file命令查看文件类型是否与后缀匹配很容易识别。

我们还可以做的更加高级一点。下图将ELF可执行二进制文件附加在有效的图片文件中,通过file指令得到正确的文件类型,且该图片可以正常显示:


该种隐藏方式需要我们更加深入的查看所有的资源文件。看着是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工具奔溃。如下图:



该方式常用于开发者阻止破解者逆向分析代码逻辑。 该方法已经被Lohan+ (AntiLVL) / jcase /和其它项目中使用。但是这种方式也有明显的缺点,可以根据异常信息很容易的修复分析工具。


2、利用已知的JAR hack方法


由于APK本质上就是zip/jar包,所以我们也可以利用已知的JAR hack方法。

JAR对文件名的长度是没有现在的,但是操作系统要求文件名不能大于255;我们可以通过构建大于255字符的长类名来达到反逆向的目的。

如何构建大于255的长类名呢?首先我们看一下DEX Class Def Item的格式:



我们可以通过以下方式构建大于255的长类名:

1、在源代码中添加大于255的字符串A。

2、编译源代码,修改DEX文件头,修改Class descriptor_id为字符串A的String_idx


下图是修改前后比较:



修改后的APK能够正常安装,如下图:




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




通过异常我们应该可以看出为什么大于255个字符会报错了吧。

但是该种方式缺点是只能对付backsmali。 IDA、Dex2jar、Androguard仍然能够正常工作。

该种方法易于检测和解决,当class名字长度>255要警惕该应用。

3、插入无效字节码指令引发逆向工具崩溃


由于大部分逆向工具都是线性读取字节码并解析,当遇到无效字节码时,就会引起反编译工具字节码解析失败。

我们可以插入无效字节码到DEX文件,但要保证该无效字节码永远不会被执行(否则您的程序就会崩溃了!)。

1201 // Load 0 into v13801 0300 // A conditional jump which should always succeed, jumps over// next bytesFFFF // Bad opcodes

安装插入无效字节码的apk文件。如下图:



但是执行程序时,却报如下的错误:

运行的时候怎么会报错呢?

Dalvik虚拟机并没有像我们预想的那样跳过无效的字节码,它会在执行之前验证所有调用序列上类的字节码是否有效。

现在的问题是如何能够绕过Dalvik虚拟机的代码验证呢?

我们如果插入无效代码在一个从来不会调用的类上不就可以绕过Dalvik运行时代码验证了吗!

看如下插入后的运行结果:

哈哈,成功运行了,接下来让我们看看该种方式反逆向的效果吧!

(可惜的backsmali已经在版本2f81aec886d2修复了该bug,该方式已无效)


Dex2jar 验证可行。

Androguard验证可行,(可惜的是Androguard很快修复了该bug)


IDA验证未成功!


ded工具验证成功!在你杀死该工具进程之前,它将一直运行在无效字节码所在类处理过程中。

该种方法的缺点是很容易被工具修复。工具在反编译代码时,只要忽略会无效字节码的处理即可,backsmali、androgurad已经修复了该bug。

该种方式和很容易被自动化监测,如果遇到无效代码就要警惕!

逆向分析人员要尽量使用工具的最新版本。


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


插入无效的字节码指令目前工具已经可以正常工作,但是如果我们插入有效的字节码指令,但是后跟无效的数据引用,结果会是怎么样呢?

1201 // Load 0 into v13801 0300 // A conditional jump which should always succeed, jumps over// next bytes1a00 FF00 // Load const-string at index 255 (doesn’t exist)
这次我们仍然绕过Dalvik运行时字节码指令验证,但是我们替换“无效字节码指令”为合法字节码指令


backsmali验证成功!


dex2jar验证成功!


Androguard验证成功,但是只会在反编译插入该“有效字节码指令”的方法报错。


ded验证成功!


IDA验证失败!


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


5、针对java反编译器缺陷进行攻击

dex2jar+(JD-Gui或JAD) 组合工具是逆向分析经常使用的工具。dex2jar用于把DEX文件转换为java字节码JAR文件,JD-GUI或JAD用于把java字节码转化为java源代码。

我们可以针对JAVA JD-Gui或JAD工具缺陷来达到反逆向分析的目的。达到的效果如下图所示:



6、针对backsmali对文件头处理缺陷

我们刚才讲到baksmali在处理Link section的bug,还有类似的崩溃点吗?如图backsmali代码所示:


当DEX Header size 不等于0x70时,backsmali也会抛出异常退出!

Header_size 当前值正常情况下都等于0x70


构建这种dex文件很容易实现。

需要修复文件头每个表项的偏移量。

修改后的Header size 等于0x78



但是这种方式只能针对baksamli工具。且很工具很容易修复该bug。

该方式也可以用于在DEX Header中隐藏数据和代码。

我们可以在Dex文件头隐藏另一个DEX数据并在运行时加载附带DEX数据。

构建非规范的Dex文件



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



通过反射实际调用DexFile的openDexFile方法


该种方式允许我们通过byte[]解析dex数据,而无须在再把DEX数据存储在设备的某个文件。

我们可以从安装APK文件、内存或dalvik-cache等读取dex数据。

打包好的DEX文件如下图所示:

该种方式将给自动化分析工具带来一个问题,自动化工具会按照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虚拟机和移动设备上很多属性是不同的。比如:



getprop Android SDK中并没有公开接口,不过我们可以通过JAVA反射调用。



五、相关引用

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

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. Android代码混淆官方实现方法
  4. Android(安卓)Dex文件结构
  5. Android(安卓)NDK 的学习之旅-----HelloWorld
  6. Android(安卓)解压zip文件
  7. android linux 基础知识总结
  8. Android(安卓)Studio代码混淆,开启Proguard,稍微总结一下
  9. Android全部源码导入Eclipse

随机推荐

  1. 如何直接使用Android(安卓)internal and
  2. android强制横屏息屏后重新打开时会先显
  3. android 详细解答json解析与生成 JSONObj
  4. android超多开发资源整理
  5. 关于android中进行http通信的几个问题
  6. android源代码编译
  7. Android下如何计算要显示的字符串所占的
  8. json连接中央气象台api异常
  9. Android(安卓)获取麦克风音量
  10. 【Androidd Release】AndroidStudio 发布