绕过Dalvik验证技术分析

来源:互联网 发布:packet tracer mac版 编辑:程序博客网 时间:2024/05/28 15:58

该漏洞是Jurrian Bremer在2013年的hack lu上提出的,主要原理是通过修改dex文件中的某些标志位来绕过Dalvik虚拟机对dex文件合法性的验证。


1.dex文件格式

dex文件如下图所示:




从图中可以看出dex文件主要分为三个部分:即简单的文件头部,各种索引结构区(紧凑的数据结构)以及数据段存储各种数据和实际执行的Dalvik 代码。


2.odex文件与dex文件

odex文件是OptimizedDEX的缩写,表示经过优化的dex文件。由于Android程序的apk文件为zip压缩包格式,Dalvik虚拟机每次加载都需要从apk中读取classes.dex文件,这会耗费很多cpu时间,而采用odex方式优化的dex文件已经包含了加载dex必须的依赖库文件列表,Dalvik虚拟机只需检测并加载所需的依赖库即可执行相应的dex文件,大大缩短了读取dex文件所需的时间。同时,Android专门提供了一个验证与优化dex文件的工具dexopt,Dalvik虚拟机在加载一个dex文件时,通过指定的验证与优化选项来调用dexopt进行相应的验证与优化操作。

而DexOpt对Dalvik指令的验证时需要检查是否所有的分支都指向合法的代码,即检查外界的代码访问,其中主要检查规则如下:

  ·对象不允许做运算 ;

  ·字符串不能执行“array-length”指令;

  ·不能通过“invoke-static”调用虚方法;

  ·指令的参数数量和种类必须和 prototypes里的一样。

这样就保证了经过检查后的代码不会吧被外界代码访问,即被检查过的Dalvik指令都是合法的指令序列。


3.漏洞原理

Dex文件中有一个标志位是access_flag,其说明文档如下图所示:



从图中可以看出,该标志位的0x00010000和0x00020000在开发者文档中是不合法的(还未使用),而在程序实际运行中,可以将这两个设置为为aceess_flag的的一部分:

libdex/DexFile.h:



另一方面Dex文件中还有两个标志CLASS_ISOPTIMIZED和CLASS_ISPREVERIFIED,这两个标志位若为1则标示该dex文件已经经过验证与优化,其验证时的执行代码如下图所示:

oo/Object.h:



如果Dex文件中类的CLASS_ISOPTIMIZED和CLASS_ISPREVERIFIED值为1时则会认为Dex文件已经被验证和优化过,从而跳过对其代码的检查。

而漏洞在于这两个标志位与aceess_flag使用同一个域,即正好位于第17和18位。简单地说,即当攻击者将dex文件中类的aceess_flag的第17和18位的值改为1,那么将覆盖CLASS_ISOPTIMIZED和CLASS_ISPREVERIFIED的值使其变为1,使得系统认为该文件已经被验证和优化过。


4.可以利用的地方?

Dexopt对dex文件的验证中其中一个是对dex文件中的Dalvik指令的合法性的验证,即检查越界的代码访问,不允许对对象进行运算处理,相应的,如果是odex文件则会跳过检测执行非法运算。这样,攻击者就能直接用java中的读取地址函数对对象进行读地址操作:

int address(Object obj){return (int) obj; };

因此,攻击者通过这种修改标志位的方式,攻击者就能在程序中读出对象的内存地址,导致对象的内存地址泄露。


5.demo和检测方法

为了证明这个漏洞的存在,Jurrian Bremer还放出了一个简单的demo,可以由用户输入任何合法的dalvik代码直接在应用中执行,但是本人在android模拟器上运行时会崩溃。

由上述的漏洞原理可以看到,通过修改dex文件中类的access_flag标志位,将该标志位的17和18位设为1,即可覆盖CLASS_ISOPTIMIZED和CLASS_ISPREVERIFIED的值,从而跳过对dex文件的检查。因此自动化检测方法也比较简单,可以考虑利用androguard中的分析工具列出dex文件中所有的类,然后检查每个类的access_flag标志位的值,若该标志位的17和18位的值为1,那么可以判断该类存在内存地址泄露的漏洞。



0 0