TaintDroid剖析之DVM变量级污点跟踪(下篇)
TaintDroid剖析之DVM变量级污点跟踪(下篇)
作者:简行、走位@阿里聚安全
1 回顾
在上一章节中我们详细分析了TaintDroid对DVM方法参数和方法变量的变量级污点跟踪机制,现在我们将继续分析TaintDroid对类的静态域、实例域以及数组的污点跟踪。
2 了解DVM中类的数据结构
由于DVM师从JVM,所以DVM中所有类的祖先也是Object类,该类定义在dalvik/vm/oo/Object.h中。其实不仅仅是Object类,DVM所有的基本类都定义在Object.h文件中。
众所周知,Object类共分三种类型:
1)Class Objects,它是java.lang.Class的实例,此类object的公共基类是ClassObject;
2)Array Objects,由new Array指令创建,此类object的公共基类是ArrayObject;
3)Data Objects,除了上面两种Object之外的所有object,公共基类是DataObject。
这里有一个特例需要注意,那就是String Objects!String Objects当前等同于Data Objects,但鉴于该类在DVM中大量使用,因此DVM单独定义了一个类StringObject,它直接继承至Object。
了解了类的数据结构,再去分析TaintDroid对类的静态域、实例域和数组的污点跟踪就不会觉得无从下手了。
3 对各种数据结构的修改
要想实现对类的实例域和静态域的污点跟踪,最简单粗暴的方式就是对类中相关的数据结构进行修改。TaintDroid就是这么做的。
1)首先,修改了ClassObject::Object:
struct ClassObject : Object { /* leave space for instance data; we could access fields directly if we freeze the definition of java/lang/Class */ #ifdef WITH_TAINT_TRACKING // x2 space for interleaved taint tags u4 instanceData[CLASS_FIELD_SLOTS*2]; #else u4 instanceData[CLASS_FIELD_SLOTS]; #endif /*WITH_TAINT_TRACKING*/ |
TaintDroid将其中的u4 instanceData[CLASS_FILED_SLOTS]改为u4 instanceData[CLASS_FILED_SLOTS * 2]。这里CLASS_FILED_SLOTS默认为4。倍增的空间用于交叉存储各个实例域的污点。联想到类的实例域有两种类型:1)诸如int之类的基本类型;2)类对象的引用。所以我们可以知道,TaintDroid为每个引用也分配了一个tag,用于表示该引用的污点信息。充分理解这一点,对我们后续分析复杂污点传播逻辑很有帮助。
2)其次,修改了静态域StaticField:Field:
struct StaticField : Field { JValue value; /* initially set from DEX for primitives */ #ifdef WITH_TAINT_TRACKING Taint taint; #endif }; |
在JValue之后添加了Taint tiant成员。Taint成员定义在vm/interp/Taint.h文件中定义如下:
typedef struct Taint{ u4 tag}Taint;
通过这样的修改,再对涉及到操作这些数据结构的方法进行修复就能实现类的实例域和静态域的污点跟踪了。这里以computeFieldOffsets函数为例,此函数定义在dalvik/vm/oo/Class.cpp中,由于代码较多,仅截取部分修复相关部分:
…… if (clazz->super != NULL) fieldOffset = clazz->super->objectSize; else fieldOffset = OFFSETOF_MEMBER(DataObject, instanceData); …… /*Start by moving all reference fields to the front */ for (i = 0; i < clazz->ifieldCount; i++) { InstField* pField = &clazz->ifields[i]; char c = pField->signature[0]; if (c != '[' && c != 'L') { while (j > i) { InstField* refField = &clazz->ifields[j--]; char rc = refField->signature[0]; if (rc == '[' || rc == 'L'] { swapField(pField, refField); c = rc; clazz->ifieldRefCount++; break; } } /* We may or may not have swapped a field.*/ } else { /* This is a reference field.*/ clazz->ifieldRefCount++; } /*If we've hit the end of the reference fields, break.*/ if (c != '[' && c != 'L') break; pField->byteOffset = fieldOffset; #ifdef WITH_TAINT_TRACKING fieldOffset += sizeof(u4) + sizeof(u4); /* interleaved tag */ #else fieldOffset += sizeof(u4); #endif LOGVV(" --- offset1 '%s'=%d", pField->name,pField->byteOffset); } …… /* Alignment is good, shuffle any double-wide fields forward, and finish assigning field offsets to all fields.*/ for ( ; i < clazz->ifieldCount; i++) { InstField* pField = &clazz->ifields[i]; char c = pField->signature[0]; if (c != 'D' && c != 'J') { while (j > i) { InstField* doubleField = &clazz->ifields[j--]; char rc = doubleField->signature[0]; if (rc == 'D' || rc == 'J') { swapField(pField, doubleField); c = rc; break; } } } else { } pField->byteOffset = fieldOffset; #ifdef WITH_TAINT_TRACKING fieldOffset += sizeof(u4) + sizeof(u4); /* room for tag */ if (c == 'J' || c == 'D') fieldOffset += sizeof(u4) + sizeof(u4); /* keep 64-bit aligned */ #else fieldOffset += sizeof(u4); if (c == 'J' || c == 'D') fieldOffset += sizeof(u4); #endif /* ndef WITH_TAINT_TRACKING */ } |
显然,在计算类中各个实例域的偏移值的时候,由于TaintDroid对实例域的空间进行了倍增(交叉存储污点),所以这里应该加上2*sizeof(u4)。另外需要注意的是对于Double和Long类型的数据,要加上4*sizeof(u4)!
至此类的实例域和静态域的污点跟踪分析完毕,下一步轮到数组了。
3)对数组对象ArrayObject:Object的修改:
struct ArrayObject : Object { /* number of elements; immutable after init */ u4 length; #ifdef WITH_TAINT_TRACKING Taint taint; #endif u8 contents[1]; }; |
在length成员之后添加Taint tiant成员。之所以这样做,是因为出于性能的考虑:如果数组中每个成员都存储一个tag的话,对性能的影响就太大了,所以TaintDroid对每个ArrayObject对象只分配一个tag。
同样的,修改了ArrayObject的结构体,就必须同步修改涉及到对ArrayObject进行操作的函数。这里以oo/Array.cpp中的allocArray函数为例:
static ArrayObject* allocArray(ClassObject* arrayClass, size_t length, size_t elemWidth, int allocFlags) { …… ArrayObject* newArray = (ArrayObject*)dvmMalloc(totalSize, allocFlags); if (newArray != NULL) { DVM_OBJECT_INIT(newArray, arrayClass); newArray->length = length; #ifdef WITH_TAINT_TRACKING newArray->taint.tag = TAINT_CLEAR; #endif dvmTrackAllocation(arrayClass, totalSize); } } |
在分配一个新的数组的时候,TaintDroid将它的taint成员赋值为TAINT_CLEAR(即清空污点信息)。
4)特殊类StringObject的结构分析。它的结构体如下:
struct StringObject : Object { /* variable #of u4 slots; u8 uses 2 slots */ u4 instanceData[1]; /** Returns this string's length in characters. */ int length() const; /** * Returns this string's length in bytes when encoded as modified UTF-8. * Does not include a terminating NUL byte. */ int utfLength() const; /** Returns this string's char[] as an ArrayObject. */ ArrayObject* array() const; /** Returns this string's char[] as a u2*. */ const u2* chars() const; }; |
由于StringObject提供了一个方法array(),此方法返回一个ArrayObject型指针,所以在获取和设置StringObject的污点信息的时候,需要通过StringObject.array()->taint.tag进行操作。
4 进一步分析DVM污点传播逻辑
在前一章节中,我们分析了两参数相加的DVM opcode(OP_ADD_INT_2ADDR),这是因为我们当时对类的静态域、实例域以及数组的污点存储并不熟悉,所以也就仅仅能捏一捏这类软柿子而已,现在我们挑战一下更高难度的数组操作相关的opcode——OP_AGET_OBJECT(即aget-obj)。该opcode的汇编实现在dalvik/vm/mterp/armv*te_taint/OP_AGET_OBJECT.S文件中:
%verify "executed" %include "armv5te_taint/OP_AGET.S" |
转到OP_AGET.S:
%default { "load":"ldr", "shift":"2" } //表示移位基准为2位,即乘以4 %verify "executed" /* * Array get, 32 bits or less. vAA <- vBB[vCC]. * * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 * instructions. We use a pair of FETCH_Bs instead. * * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short */ /* op vAA, vBB, vCC */ FETCH_B(r2, 1, 0) @ r2<- BB mov r9, rINST, lsr #8 @ r9<- AA FETCH_B(r3, 1, 1) @ r3<- CC GET_VREG(r0, r2) @ r0<- vBB (array object) GET_VREG(r1, r3) @ r1<- vCC (requested index) cmp r0, #0 @ null array object? beq common_errNullObject @ yes, bail // begin WITH_TAINT_TRACKING bl .L${opcode}_taint_prop_1 // end WITH_TAINT_TRACKING ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width cmp r1, r3 @ compare unsigned index, length // begin WITH_TAINT_TRACKING // bcs common_errArrayIndex @ index >= length, bail // in subroutine // FETCH_ADVANCE_INST(2) @ advance rPC, load rINST // in subroutine bl .L${opcode}_taint_prop_2 // end WITH_TAINT_TRACKING $load r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] GET_INST_OPCODE(ip) @ extract opcode from rINST SET_VREG(r2, r9) @ vAA<- r2 GOTO_OPCODE(ip) @ jump to next instruction %break .L${opcode}_taint_prop_1: ldr r2, [r0, #offArrayObject_taint] @获取数组对象vBB的taint,赋给r2 SET_TAINT_FP(r10) GET_VREG_TAINT(r3, r3, r10) @获取索引数据vCC的taint,赋给r3 orr r2, r3, r2 @ r2<- r2 | r1 bx lr .L${opcode}_taint_prop_2: bcs common_errArrayIndex @ index >= length, bail FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_TAINT_FP(r3) SET_VREG_TAINT(r2, r9, r3) @将r2(即此时的污点信息)赋值给vAA的taint tag bx lr |
显然重点在*_taint_prop_1和*_taint_prop_2两个代码段。简要概括它们的功能:
1)taint_prop_1首先取得数组对象vBB的taint。注意这里offArrayObject_taint定义在dalvik/vm/common/asm-constants.h中:
#ifdef WITH_TAINT_TRACKING MTERP_OFFSET(offArrayObject_taint, ArrayObject, taint, 12) //结合ArrayObject数据结构,不难理解此代码 #endif MTERP_OFFSET宏的定义如下: # define MTERP_OFFSET(_name, _type, _field, _offset) \ if (OFFSETOF_MEMBER(_type, _field) != _offset) { \ ALOGE("Bad asm offset %s (%d), should be %d", \ #_name, _offset, OFFSETOF_MEMBER(_type, _field)); \ failed = true; \ } |
获取了vBB的taint tag之后,再获取索引vCC的taint tag,然后将两者相或,最终结果赋给r2寄存器;
2)taint_prop_2再将此时的r2寄存器中的tag信息赋值给vAA的taint tag。这样就完成了aget-object的污点传播了。
至此整个DVM的变量级污点跟踪机制我们都已经分析完毕,下一步就是分析Native层的方法级污点跟踪,这里给各位读者预留一个问题:为什么在DVM中可以实现变量街污点跟踪,但是native层却只能实现方法级污点跟踪呢?
作者:简行、走位@阿里聚安全,更多技术文章,请访问阿里聚安全博客
TaintDroid剖析之DVM变量级污点跟踪(下篇)的更多相关文章
- TaintDroid剖析之Native方法级污点跟踪分析
1.Native方法的污点传播 在前两篇文章中我们详细分析了TaintDroid对DVM栈帧的修改,以及它是如何在修改之后的栈帧中实现DVM变量级污点跟踪的.现在我们继续分析其第二个粒度的污点跟踪—— ...
- TaintDroid剖析之File & Memiry & Socket级污点传播
TaintDroid剖析之File & Memiry & Socket级污点传播 作者:简行.走位@阿里聚安全 1.涉及到的代码文件 TaintDroid在File, Memory以及 ...
- TaintDroid剖析之IPC级污点传播
TaintDroid剖析之IPC级污点传播 作者:简行.走位@阿里聚安全 前言 在前三篇文章中我们详细分析了TaintDroid对DVM栈帧的修改,以及它是如何在修改之后的栈帧中实现DVM变量级污点跟 ...
- TaintDroid:智能手机监控实时隐私信息流跟踪系统(一)
1.1 摘要 现今,智能手机操作系统不能有效的提供给用户足够的控制权并且很清楚的了解到第三方的应用程序是如何使用其的隐私数据.我们使用了TaintDroid来阐明这个缺点,其是一个高效的,全系 ...
- TaintDroid:智能手机监控实时隐私信息流跟踪系统(三)
4.3 原生代码标记传播 Native 代码是不受TaintDroid监控的.理想情况下,我们获得了相同的传播语义当使用相同的解释副本时.因此,为了精确的在Java层进行污点监控,我们定义了两个必 ...
- TaintDroid:智能手机监控实时隐私信息流跟踪系统(四)
6 应用程序研究 款流行的应用程序是怎么使用用户敏感数据的.选取的应用程序可以根据相应的权限通过Internet获得各种各样的用户数据.我们研究发现三分之二的这些数据暴露了用户详细的地理位置 ...
- TaintDroid深入剖析之启动篇
1 背景知识 1.1 Android平台软件动态分析现状 众所周知,在计算机领域中所有的软件分析方法都可以归为静态分析和动态分析两大类,在Android平台也不例外.而随着软件加固.混淆技术的不 ...
- 开始写Effective系列总结一些前端的心得
确实是没有时间整理以及总结和发表自己的感慨.难得中秋银行的事情搞完了自己清闲3天,是时候总结一下从大公司做.NET PC 端网站的开发到现在做移动互联网的银行及政府微信公众号的开发的感触.当时自己的选 ...
- TaintDroid简介
1.Information-Flow tracking,Realtime Privacy Monitoring.信息流动追踪,实时动态监控. 2.TaintDroid是一个全系统动态污点跟踪和分析系统 ...
随机推荐
- pkcs1与pkcs8格式RSA私钥互相转换
转自:http://blog.csdn.net/duan19056/article/details/52104966 1.PKCS1私钥生成 openssl genrsa -out private.k ...
- 解决文件上传插件Uploadify在火狐浏览器下,Session丢失的问题
因为在火狐浏览器下Flash发送的请求不会带有cookie,所以导致后台的session失效. 解决的方法就是手动传递SessionID到后台. $("#fileresultfiles&qu ...
- Jenkins配置自动发送邮件,成功!
Jenkins自动发送邮件配置: 打开"系统管理"--"系统设置" 在"Jenkins Location"设置系统管理员地址(重要:不能省略 ...
- Error:Execution failed for task ':clean'. > Unable to delete directory :\build\intermediates (转)
第一种方法: build文件夹,可以使用360文件粉碎机删除,然后重启Android Studio即可! 转自 第二种方法: 进入studio,进入settings,搜索instant run,进入该 ...
- 一个年轻的码农的一个C#项目
话不多少,今天要写一个小项目.我们写项目要做好准备.我们要做项目分析.要知道用户需求,然后在根据需求来规划自己的项目.我们要用自己所学,做最好的程序.尽自己所能完成项目需求.精简代码! 我们今天要写的 ...
- [leetcode] 数字游戏
169. Majority Element Given an array of size n, find the majority element. The majority element is t ...
- mac版Camtasia 2.10破解
Camtasia是非常好用的一款录屏.视频编辑.制作的软件.但是这么一款优秀的软件只有30天的试用期,试用期过后便不能使用. 目前网上的破解办法几乎都属于同一种办法: http://www.orsoo ...
- keycode
<script type="text/javascript" language=JavaScript charset="UTF-8"> docume ...
- 修改redhat 源
关于免费解决RedHat6.5的:This system is not registered to Red Hat Subscription Managemenredhat默认自带的yum源需要注册, ...
- 返水bug-备用
NOOK(N) CSBFB(25) off(Y) QQ(2652880032) G(1) off1(Y) QQ1(3479301404) G1(1) off2(Y) QQ2(309235846) G2 ...