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 tagsu4              instanceData[CLASS_FIELD_SLOTS*2];
#elseu4              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_TRACKINGTaint           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;elsefieldOffset = 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_TRACKINGfieldOffset += sizeof(u4) + sizeof(u4); /* interleaved tag */
#elsefieldOffset += sizeof(u4);
#endifLOGVV("  --- 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_TRACKINGfieldOffset += sizeof(u4) + sizeof(u4); /* room for tag */if (c == 'J' || c == 'D')fieldOffset += sizeof(u4) + sizeof(u4); /* keep 64-bit aligned */
#elsefieldOffset += sizeof(u4);if (c == 'J' || c == 'D')fieldOffset += sizeof(u4);
#endif /* ndef WITH_TAINT_TRACKING */}

显然,在计算类中各个实例域的偏移值的时候,由于TaintDroid对实例域的空间进行了倍增(交叉存储污点),所以这里应该加上2sizeof(u4)。另外需要注意的是对于Double和Long类型的数据,要加上4sizeof(u4)!

至此类的实例域和静态域的污点跟踪分析完毕,下一步轮到数组了。

3)对数组对象ArrayObject:Object的修改:

struct ArrayObject : Object {/* number of elements; immutable after init */u4              length;
#ifdef WITH_TAINT_TRACKINGTaint           taint;
#endifu8              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_TRACKINGnewArray->taint.tag = TAINT_CLEAR;
#endifdvmTrackAllocation(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<- BBmov     r9, rINST, lsr #8           @ r9<- AAFETCH_B(r3, 1, 1)                   @ r3<- CCGET_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_TRACKINGbl                .L${opcode}_taint_prop_1
// end WITH_TAINT_TRACKINGldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->lengthadd     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*widthcmp     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 subroutinebl                .L${opcode}_taint_prop_2
// end WITH_TAINT_TRACKING$load   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]GET_INST_OPCODE(ip)                 @ extract opcode from rINSTSET_VREG(r2, r9)                    @ vAA<- r2GOTO_OPCODE(ip)                     @ jump to next instruction%break.L${opcode}_taint_prop_1:ldr            r2, [r0, #offArrayObject_taint]   @获取数组对象vBB的taint,赋给r2SET_TAINT_FP(r10)GET_VREG_TAINT(r3, r3, r10)                  @获取索引数据vCC的taint,赋给r3orr            r2, r3, r2                  @ r2<- r2 | r1bx            lr.L${opcode}_taint_prop_2:bcs     common_errArrayIndex        @ index >= length, bailFETCH_ADVANCE_INST(2)               @ advance rPC, load rINSTSET_TAINT_FP(r3)SET_VREG_TAINT(r2, r9, r3)            @将r2(即此时的污点信息)赋值给vAA的taint tagbx      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数据结构,不难理解此代码
#endifMTERP_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 变量级污点跟踪(下篇)相关推荐

  1. TaintDroid剖析之DVM变量级污点跟踪(下篇)

    TaintDroid剖析之DVM变量级污点跟踪(下篇) 简行.走位@阿里聚安全 1 回顾 在上一章节中我们详细分析了TaintDroid对DVM方法参数和方法变量的变量级污点跟踪机制,现在我们将继续分 ...

  2. 最大功率点跟踪_华北电力大学颜湘武团队特稿:基于变功率点跟踪和超级电容器储能协调控制的双馈风电机组一次调频策略...

    武汉加油 风雨同行 共克时艰 点击下面标题,了解通知详情第九届电工技术前沿问题学术论坛征文通知团队介绍 颜湘武,博士,教授,博士生导师,"分布式储能与微网"河北省重点实验室副主任, ...

  3. java获取长度_获取java长度

    Java获取本机MAC地址 为什么写这个呢?因为前几天看见网上有采用windows命令获取局域网和广域网MAC,查了查可以直接用JDK的方法. MAC可用于局域网验证,提高安全性. import ja ...

  4. TaintDroid深入剖析之启动篇

    TaintDroid深入剖析之启动篇 1 背景知识 1.1 Android平台软件动态分析现状 众所周知,在计算机领域中所有的软件分析方法都可以归为静态分析和动态分析两大类,在Android平台也不例 ...

  5. linux修改字符集为amer,Linux数据库的创建 导入导出 以及一些基本指令

    首先linux 下查看mysql相关目录 查看 mysql 的安装路径 执行查询 SQL mysql>show variables like '%dir%'; datadir 就是数据路径 确定 ...

  6. AD2S1205替代 国产旋变数字转换器—MS5905P

    瑞盟 MS5905P为 国产12bit旋变数字转换器, 最大跟踪速率达到了1250rps,角度精度为正负11弧分,PIN 2 PIN兼容进口ADI AD2S1205, 管脚兼容,封装兼容,软件兼容,参 ...

  7. 前瞻《飞驰人生》陈一愚:变与不变是韩寒自我经历投射

    中新网1月30日电 2019年春节档强片如云,而电影<飞驰人生>在春节档中预售表现抢眼.韩寒此前有第一部作品<后会无期>第二部作品<乘风破浪>,<飞驰人生&g ...

  8. cmd怎么运行http_Scrapy源码剖析(二)Scrapy是如何运行起来的?

    阅读本文大约需要 15 分钟.本文章代码较多,如果手机端阅读体验不好,建议先收藏后在 PC 端阅读. 在上篇文章:Scrapy源码剖析(一)架构概览,我们主要从整体上了解了 Scrapy 的架构和数据 ...

  9. Android Binder IPC机制

    之前有很多人问过我TaintDroid的内容,所以一点点吧涉及的思路整理一下. 今天又看了一遍,确实需要很多的技术支持以及扎实的功底,不管是Java的还是Android,从系统底层一直到顶层,涉及的知 ...

最新文章

  1. python中怎么把值添加进列表_在Python中为子列表添加值
  2. 美团面试:JVM 堆内存溢出后,其他线程是否可继续工作?
  3. 行代码入门python_新浪微博Android客户端开发视频教程(36讲)
  4. JZOJ__Day 9:【普及模拟】Square
  5. fortran的gui开发 python_python和fortran的接口
  6. java环境变量path好长_java环境变量设置
  7. 网页中竖的目录怎么改成横的_怎么学习手绘插画?小白也能入门哦
  8. 第3章 变量和表达式
  9. 【华为云实战开发】1.传统Java项目怎么能变得高大上?
  10. 全是大事:百度华为联手搞AI;滴滴再融40亿美元也说搞AI
  11. 如何在Python中读取属性文件?
  12. 到底啥是平台,到底啥是中台?李鬼太多,不得不说
  13. 基于大数据的图书推荐系统
  14. 带你区分超键,候选键,主键
  15. 红米k50 刷入类原生教程
  16. CentOS下搭建Frp内网穿透服务
  17. tplink控制上网设备_tplink路由器如何控制小孩的使用上网时间
  18. HTTP传输协议详解(传输过程及数据格式详细)
  19. 随机事件及其概率运算
  20. UI设计规范有哪些?| 萧蕊冰

热门文章

  1. 秒杀系统架构设计与分析
  2. oppor15android10怎么降级,OPPOR15系统降级教程
  3. ubuntu 黑体_Ubuntu 7.10 黑体解决方案
  4. 电脑重装系统蓝屏详细解决方法分享
  5. 数据库系统设计_银行业务管理系统
  6. 695N开发调试总结
  7. 非线性混合效应 NLME模型对抗哮喘药物茶碱动力学研究
  8. 吃海鲜搭配什么菜好 搭配这些健康又美味
  9. 在K8s上轻松部署Tungsten Fabric的两种方式
  10. DNS云监控出现问题如何解决