国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

TaintDroid 剖析之 DVM 變量級(jí)污點(diǎn)跟蹤(下篇)

JeOam / 1646人閱讀

摘要:回顧在上一章節(jié)中我們?cè)敿?xì)分析了對(duì)方法參數(shù)和方法變量的變量級(jí)污點(diǎn)跟蹤機(jī)制,現(xiàn)在我們將繼續(xù)分析對(duì)類的靜態(tài)域?qū)嵗蛞约皵?shù)組的污點(diǎn)跟蹤。充分理解這一點(diǎn),對(duì)我們后續(xù)分析復(fù)雜污點(diǎn)傳播邏輯很有幫助。對(duì)數(shù)組對(duì)象的修改在成員之后添加成員。

1 回顧

在上一章節(jié)中我們?cè)敿?xì)分析了TaintDroid對(duì)DVM方法參數(shù)和方法變量的變量級(jí)污點(diǎn)跟蹤機(jī)制,現(xiàn)在我們將繼續(xù)分析TaintDroid對(duì)類的靜態(tài)域、實(shí)例域以及數(shù)組的污點(diǎn)跟蹤。

2 了解DVM中類的數(shù)據(jù)結(jié)構(gòu)

由于DVM師從JVM,所以DVM中所有類的祖先也是Object類,該類定義在dalvik/vm/oo/Object.h中。其實(shí)不僅僅是Object類,DVM所有的基本類都定義在Object.h文件中。

眾所周知,Object類共分三種類型:

Class Objects,它是java.lang.Class的實(shí)例,此類object的公共基類是ClassObject;

Array Objects,由new Array指令創(chuàng)建,此類object的公共基類是ArrayObject;

Data Objects,除了上面兩種Object之外的所有object,公共基類是DataObject。

這里有一個(gè)特例需要注意,那就是String Objects!String Objects當(dāng)前等同于Data Objects,但鑒于該類在DVM中大量使用,因此DVM多帶帶定義了一個(gè)類StringObject,它直接繼承至Object。

了解了類的數(shù)據(jù)結(jié)構(gòu),再去分析TaintDroid對(duì)類的靜態(tài)域、實(shí)例域和數(shù)組的污點(diǎn)跟蹤就不會(huì)覺(jué)得無(wú)從下手了。

3 對(duì)各種數(shù)據(jù)結(jié)構(gòu)的修改

要想實(shí)現(xiàn)對(duì)類的實(shí)例域和靜態(tài)域的污點(diǎn)跟蹤,最簡(jiǎn)單粗暴的方式就是對(duì)類中相關(guān)的數(shù)據(jù)結(jié)構(gòu)進(jìn)行修改。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默認(rèn)為4。倍增的空間用于交叉存儲(chǔ)各個(gè)實(shí)例域的污點(diǎn)。聯(lián)想到類的實(shí)例域有兩種類型:1)諸如int之類的基本類型;2)類對(duì)象的引用。所以我們可以知道,TaintDroid為每個(gè)引用也分配了一個(gè)tag,用于表示該引用的污點(diǎn)信息。充分理解這一點(diǎn),對(duì)我們后續(xù)分析復(fù)雜污點(diǎn)傳播邏輯很有幫助。

2)其次,修改了靜態(tài)域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;

通過(guò)這樣的修改,再對(duì)涉及到操作這些數(shù)據(jù)結(jié)構(gòu)的方法進(jìn)行修復(fù)就能實(shí)現(xiàn)類的實(shí)例域和靜態(tài)域的污點(diǎn)跟蹤了。這里以computeFieldOffsets函數(shù)為例,此函數(shù)定義在dalvik/vm/oo/Class.cpp中,由于代碼較多,僅截取部分修復(fù)相關(guān)部分:

……
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 */
    }

顯然,在計(jì)算類中各個(gè)實(shí)例域的偏移值的時(shí)候,由于TaintDroid對(duì)實(shí)例域的空間進(jìn)行了倍增(交叉存儲(chǔ)污點(diǎn)),所以這里應(yīng)該加上2sizeof(u4)。另外需要注意的是對(duì)于Double和Long類型的數(shù)據(jù),要加上4sizeof(u4)!

至此類的實(shí)例域和靜態(tài)域的污點(diǎn)跟蹤分析完畢,下一步輪到數(shù)組了。

3)對(duì)數(shù)組對(duì)象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成員。之所以這樣做,是因?yàn)槌鲇谛阅艿目紤]:如果數(shù)組中每個(gè)成員都存儲(chǔ)一個(gè)tag的話,對(duì)性能的影響就太大了,所以TaintDroid對(duì)每個(gè)ArrayObject對(duì)象只分配一個(gè)tag。

同樣的,修改了ArrayObject的結(jié)構(gòu)體,就必須同步修改涉及到對(duì)ArrayObject進(jìn)行操作的函數(shù)。這里以oo/Array.cpp中的allocArray函數(shù)為例:

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);
    }
}

在分配一個(gè)新的數(shù)組的時(shí)候,TaintDroid將它的taint成員賦值為TAINT_CLEAR(即清空污點(diǎn)信息)。

4)特殊類StringObject的結(jié)構(gòu)分析。它的結(jié)構(gòu)體如下:

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提供了一個(gè)方法array(),此方法返回一個(gè)ArrayObject型指針,所以在獲取和設(shè)置StringObject的污點(diǎn)信息的時(shí)候,需要通過(guò)StringObject.array()->taint.tag進(jìn)行操作。

4 進(jìn)一步分析DVM污點(diǎn)傳播邏輯

在前一章節(jié)中,我們分析了兩參數(shù)相加的DVM opcode(OP_ADD_INT_2ADDR),這是因?yàn)槲覀儺?dāng)時(shí)對(duì)類的靜態(tài)域、實(shí)例域以及數(shù)組的污點(diǎn)存儲(chǔ)并不熟悉,所以也就僅僅能捏一捏這類軟柿子而已,現(xiàn)在我們挑戰(zhàn)一下更高難度的數(shù)組操作相關(guān)的opcode——OP_AGET_OBJECT(即aget-obj)。該opcode的匯編實(shí)現(xiàn)在dalvik/vm/mterp/armv*te_taint/OP_AGET_OBJECT.S文件中:

%verify "executed"
%include "armv5te_taint/OP_AGET.S"

轉(zhuǎn)到OP_AGET.S:

%default { "load":"ldr", "shift":"2" }   //表示移位基準(zhǔn)為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]   @獲取數(shù)組對(duì)象vBB的taint,賦給r2
    SET_TAINT_FP(r10)
    GET_VREG_TAINT(r3, r3, r10)                  @獲取索引數(shù)據(jù)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(即此時(shí)的污點(diǎn)信息)賦值給vAA的taint tag
    bx      lr

顯然重點(diǎn)在*_taint_prop_1*_taint_prop_2兩個(gè)代碼段。簡(jiǎn)要概括它們的功能:

1)taint_prop_1首先取得數(shù)組對(duì)象vBB的taint。注意這里offArrayObject_taint定義在dalvik/vm/common/asm-constants.h中:

#ifdef WITH_TAINT_TRACKING
MTERP_OFFSET(offArrayObject_taint,        ArrayObject, taint, 12) //結(jié)合ArrayObject數(shù)據(jù)結(jié)構(gòu),不難理解此代碼
#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,然后將兩者相或,最終結(jié)果賦給r2寄存器;

2)taint_prop_2再將此時(shí)的r2寄存器中的tag信息賦值給vAA的taint tag。這樣就完成了aget-object的污點(diǎn)傳播了。

至此整個(gè)DVM的變量級(jí)污點(diǎn)跟蹤機(jī)制我們都已經(jīng)分析完畢,下一步就是分析Native層的方法級(jí)污點(diǎn)跟蹤,這里給各位讀者預(yù)留一個(gè)問(wèn)題:為什么在DVM中可以實(shí)現(xiàn)變量街污點(diǎn)跟蹤,但是native層卻只能實(shí)現(xiàn)方法級(jí)污點(diǎn)跟蹤呢?

作者:簡(jiǎn)行、走位@阿里聚安全,更多技術(shù)文章,請(qǐng)?jiān)L問(wèn)阿里聚安全博客

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/11204.html

相關(guān)文章

  • TaintDroid剖析IPC級(jí)污點(diǎn)傳播

    摘要:前言在前三篇文章中我們?cè)敿?xì)分析了對(duì)棧幀的修改,以及它是如何在修改之后的棧幀中實(shí)現(xiàn)變量級(jí)污點(diǎn)跟蹤方法級(jí)跟蹤。總結(jié)的污點(diǎn)跟蹤粒度是變量粒度的,因此大大提高了污點(diǎn)傳播的精準(zhǔn)度。下一步繼續(xù)分析下級(jí)污點(diǎn)傳播。 前言 在前三篇文章中我們?cè)敿?xì)分析了TaintDroid對(duì)DVM棧幀的修改,以及它是如何在修改之后的棧幀中實(shí)現(xiàn)DVM變量級(jí)污點(diǎn)跟蹤、Native方法級(jí)跟蹤。本篇文章我們來(lái)分析下IPC級(jí)污點(diǎn)傳...

    baishancloud 評(píng)論0 收藏0
  • 淺入淺出FlowDroid(一): 簡(jiǎn)介&基本使用

    摘要:后文將圍繞做一些介紹。盡管如此,的使用對(duì)新手而言仍然充滿了困難。本系列文章基本為個(gè)人見(jiàn)解,難免有錯(cuò)誤與誤解,如有客觀錯(cuò)誤歡迎提出。 前言 說(shuō)到Android的污點(diǎn)分析框架,網(wǎng)上的搜索結(jié)果大多指向靜態(tài)的FlowDroid與動(dòng)態(tài)的TaintDroid。盡管由于加固、混淆等技術(shù)使得針對(duì)Android的靜態(tài)分析越來(lái)越困難,但靜態(tài)分析的無(wú)先驗(yàn)分析能力無(wú)法被動(dòng)態(tài)分析取代,使得靜態(tài)分析仍有發(fā)揮空間。...

    wqj97 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<