亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        基于虛擬機(jī)的程序運(yùn)行時(shí)監(jiān)控方法

        2018-01-15 09:19:58王丹陳嘉趙文兵林九川
        關(guān)鍵詞:控制流寄存器進(jìn)程

        王丹, 陳嘉, 趙文兵, 林九川

        (1.北京工業(yè)大學(xué) 信息學(xué)部,北京 100124; 2.公安部第三研究所 信息網(wǎng)絡(luò)安全公安部重點(diǎn)實(shí)驗(yàn)室,上海 201204)

        為對程序運(yùn)行時(shí)行為進(jìn)行監(jiān)控和分析,通常是在運(yùn)行時(shí)通過插樁、跟蹤調(diào)試等程序動(dòng)態(tài)分析技術(shù)來完成。動(dòng)態(tài)二進(jìn)制插樁技術(shù)[1](dynamic binary instrument,DBI),是在不改變程序原有邏輯的基礎(chǔ)上,將一些探針插入到程序中,通過執(zhí)行探針得到程序運(yùn)行的特征數(shù)據(jù),再分析這些特征數(shù)據(jù)完成對程序的分析[2-3]。DynamoRIO[4]、Valgrind[5]等是常用的動(dòng)態(tài)二進(jìn)制插樁工具,它們具有較完善的結(jié)構(gòu),但均是面向進(jìn)程的,工作在用戶層,依靠動(dòng)態(tài)插樁技術(shù)實(shí)現(xiàn)的,導(dǎo)致其難以實(shí)現(xiàn)對驅(qū)動(dòng)、多進(jìn)程、管道通信等的分析檢測,因此并不適合做與系統(tǒng)運(yùn)行相關(guān)的內(nèi)核分析。

        跟蹤調(diào)試技術(shù)使用調(diào)試器來加載程序,通過跟蹤程序運(yùn)行時(shí)調(diào)用的函數(shù)及執(zhí)行的指令等來獲取相關(guān)信息。常用的跟蹤方法有兩種:一種是使用HOOK技術(shù)監(jiān)視程序運(yùn)行調(diào)用的函數(shù)并進(jìn)行分析;二是以較長的時(shí)間代價(jià)單步跟蹤程序的執(zhí)行過程并進(jìn)行分析。但是,使用插樁技術(shù)會(huì)破壞程序運(yùn)行現(xiàn)場和數(shù)據(jù)的完整性,也容易被惡意木馬反調(diào)試技術(shù)察覺和規(guī)避。

        將程序置于虛擬機(jī)或虛擬機(jī)模擬器環(huán)境中運(yùn)行以獲取其運(yùn)行過程中的信息是另一種常用的程序運(yùn)行時(shí)監(jiān)控方法,且該方法不受多態(tài)、變形和加密及程序中的間接跳轉(zhuǎn)和間接調(diào)用指令的影響。目前常用的虛擬機(jī)模擬分析工具有TEMU[6]、DECAF(dynamic executable code analysis framework)等,它們都基于QEMU平臺(tái)。QEMU是一個(gè)通用的開源模擬器和虛擬機(jī)。作為虛擬機(jī)使用時(shí),QEMU可以在不同體系結(jié)構(gòu)的機(jī)器上運(yùn)行同一個(gè)虛擬環(huán)境,安裝操作系統(tǒng)并運(yùn)行程序,QEMU提供了多種接口供開發(fā)人員使用,采用動(dòng)態(tài)翻譯技術(shù),將虛擬環(huán)境中的目標(biāo)程序翻譯成宿主機(jī)器語言,先對基本塊進(jìn)行翻譯,然后再執(zhí)行并加以緩存,后續(xù)可直接使用緩存的代碼,無需重復(fù)翻譯。TEMU是基于QEMU開發(fā)的全系統(tǒng)的動(dòng)態(tài)二進(jìn)制分析平臺(tái),它定義了一組API,用于獲取和設(shè)置內(nèi)存及CPU寄存器的值,并增加了語義提取模塊和污點(diǎn)分析模塊,為用戶開發(fā)相關(guān)插件提供了接口。DECAF是在相關(guān)研究人員改進(jìn)TEMU不足的基礎(chǔ)上生成的一個(gè)新的二進(jìn)制框架,具有高效、污點(diǎn)信息分析完整等特性。DECAF也為開發(fā)人員提供了許多回調(diào)接口,通過這些回調(diào)接口開發(fā)人員可以開發(fā)出用于分析Guest操作系統(tǒng)執(zhí)行過程的強(qiáng)有力的插件。由于QEMU是面向系統(tǒng)的和基于事件驅(qū)動(dòng)的,工作在系統(tǒng)層,能夠較為全面地對程序執(zhí)行流程實(shí)施監(jiān)控,避免插樁技術(shù)易被反調(diào)試的弊端。因此,本文基于虛擬機(jī)模擬技術(shù)的軟件行為監(jiān)控系統(tǒng),從系統(tǒng)視角獲取操作系統(tǒng)內(nèi)核狀態(tài)和多個(gè)進(jìn)程的信息并進(jìn)行分析。設(shè)計(jì)并實(shí)現(xiàn)了基于QEMU并配置DECAF的動(dòng)態(tài)監(jiān)控平臺(tái),被測程序在QEMU虛擬環(huán)境中運(yùn)行,通過DECAF從外部監(jiān)視整個(gè)模擬器的運(yùn)行情況,獲取系統(tǒng)級信息。

        1 監(jiān)控框架及關(guān)鍵技術(shù)

        1.1 監(jiān)控框架

        圖1是總體的監(jiān)控系統(tǒng)架構(gòu)。首先在宿主機(jī)器上安裝QEMU并配置DECAF平臺(tái),然后在全系統(tǒng)模擬器QEMU上安裝Windows XP操作系統(tǒng),再在虛擬環(huán)境的操作系統(tǒng)中執(zhí)行被監(jiān)控對象(如圖1中所示的PE文件)。DECAF從外部監(jiān)視整個(gè)模擬器的運(yùn)行情況,獲取QEMU系統(tǒng)級語義信息。

        如圖2所示,被測程序在QEMU虛擬環(huán)境中運(yùn)行時(shí),QEMU通過微指令生成器將多種不同結(jié)構(gòu)的程序代碼,如x86上的Windows、x86上的Linux、MIPS上的Linux等,翻譯為統(tǒng)一的中間語言。然后,QEMU再根據(jù)宿主系統(tǒng)不同的結(jié)構(gòu),將中間語言翻譯為宿主操作系統(tǒng)可識別的機(jī)器碼,進(jìn)而運(yùn)行程序。這一系列操作對用戶來說都是透明的。與此同時(shí),DECAF在QEMU翻譯的基礎(chǔ)之上,獲取用戶分析所需的相關(guān)信息,如當(dāng)前進(jìn)程名稱、程序計(jì)數(shù)器、當(dāng)前系統(tǒng)環(huán)境等信息并進(jìn)行處理。另外,通過事件處理機(jī)制,可處理用戶注冊的感興趣的事件。當(dāng)DECAF檢測到用戶注冊的事件在模擬系統(tǒng)中發(fā)生時(shí),會(huì)觸發(fā)DECAF調(diào)用用戶注冊的響應(yīng)函數(shù),獲取當(dāng)前系統(tǒng)環(huán)境數(shù)據(jù)和被監(jiān)控程序的信息并進(jìn)行處理。

        圖1 基于虛擬機(jī)的監(jiān)控系統(tǒng)架構(gòu)Fig.1 Monitoring framework based on virtual machine

        圖2 平臺(tái)對照Fig.2 Platform contrast

        1.2 動(dòng)態(tài)二進(jìn)制翻譯

        基于虛擬機(jī)的動(dòng)態(tài)二進(jìn)制分析技術(shù),首先會(huì)對程序進(jìn)行動(dòng)態(tài)二進(jìn)制翻譯,然后再去執(zhí)行翻譯的結(jié)果。這一功能主要依賴它的動(dòng)態(tài)代碼生成器(TCG)。TCG采用動(dòng)態(tài)的翻譯方式,主要負(fù)責(zé)分析并優(yōu)化目標(biāo)代碼,然后將其翻譯為主機(jī)代碼,遵循從目標(biāo)代碼、到TCG代碼、再到主機(jī)可識別代碼這樣的流程。具體翻譯過程如下:首先,將每一條目標(biāo)代碼指令切分為若干個(gè)單元操作,每個(gè)單元操作由一段簡單的C語言代碼實(shí)現(xiàn),作為一個(gè)翻譯塊(TB)。TB是QEMU指令翻譯的基本單位,對應(yīng)目標(biāo)代碼的一條指令。在程序運(yùn)行時(shí),利用動(dòng)態(tài)代碼生成器將以上單元組合操作,以函數(shù)形式展現(xiàn)。系統(tǒng)調(diào)用這個(gè)函數(shù),就相當(dāng)于執(zhí)行了一條目標(biāo)代碼的指令。在翻譯過程中會(huì)涉及很多事件,如塊開始執(zhí)行/結(jié)束事件、內(nèi)存讀寫、被修改的內(nèi)存位置讀寫等。這些事件會(huì)在事件驅(qū)動(dòng)中觸發(fā)函數(shù)調(diào)用。通過QEMU,目標(biāo)代碼以翻譯塊為單位翻譯并生成中間代碼后放入翻譯緩存中,執(zhí)行過程如圖3所示。

        1.3 事件驅(qū)動(dòng)

        DECAF提供了簡單易用的事件驅(qū)動(dòng)程序接口,當(dāng)監(jiān)測到被注冊的事件發(fā)生時(shí),它會(huì)調(diào)用事先定義的相應(yīng)的事件處理函數(shù)。利用這一接口,分析人員根據(jù)自己的需求選擇注冊事件,并在事件發(fā)生時(shí),進(jìn)行相應(yīng)信息的提取和處理工作。因?yàn)橐谑录l(fā)生時(shí)進(jìn)行實(shí)時(shí)信息獲取,即注冊的事件在QEMU中發(fā)生后,會(huì)觸發(fā)所對應(yīng)的回調(diào)函數(shù),所以QEMU暫??蛻舨僮飨到y(tǒng)的運(yùn)行,將DECAF的回調(diào)函數(shù)作為輔助函數(shù)插入到QEMU中,然后恢復(fù)QEMU的運(yùn)行,這時(shí)回調(diào)函數(shù)就會(huì)被運(yùn)行,如圖4所示。

        圖3 翻譯過程Fig.3 Translation process

        圖4 回調(diào)函數(shù)觸發(fā)過程Fig.4 Trigger process of callback function

        當(dāng)“翻譯塊開始/結(jié)束”,“讀取/寫入被污染的內(nèi)存位置”這樣的事件發(fā)生時(shí),相應(yīng)的回調(diào)函數(shù)就會(huì)開始工作。DECAF通過接口將事件處理函數(shù)與事件相關(guān)聯(lián)。接收到事件的信號后,DECAF會(huì)在某個(gè)翻譯塊中插入一個(gè)輔助函數(shù),使客戶操作系統(tǒng)暫停運(yùn)行,將輔助函數(shù)中的指令兩次翻譯到翻譯塊中,并覆蓋原有指令,然后恢復(fù)客戶系統(tǒng)的運(yùn)行。為這些事件注冊的回調(diào)函數(shù)就會(huì)利用這些數(shù)據(jù)開始分析處理工作。因?yàn)榛卣{(diào)函數(shù)的觸發(fā)和客戶系統(tǒng)的執(zhí)行是內(nèi)聯(lián)的,所以當(dāng)事件發(fā)生時(shí),回調(diào)函數(shù)的觸發(fā)和客戶系統(tǒng)的執(zhí)行也會(huì)同時(shí)發(fā)生。

        // 開始翻譯塊

        // 觸發(fā)DECAF_BLOCK_BEGIN回調(diào)

        movi_i32 tmp21, $

        movi_i32 tmp22, $DECAF_invoke_block_begin_callback

        call tmp22, $0x0, $0, env, tmp21

        // 初始化指令: orl %ebx, %eax

        // 觸發(fā)DECAF_INSN_BEGIN回調(diào)

        movi_i32 tmp23, $DECAF_invoke_insn_begin_callback

        call tmp23, $0x0, $0, env

        mov_i32 tmp11, ebx

        mov_i32 tmp12, eax

        or_i32 tmp13, tmp12, tmp11

        // 觸發(fā)DECAF_INSN_END回調(diào)

        movi_i32 tmp24, $DECAF_invoke_insn_end_callback

        call tmp24, $0x0, $0, env

        // 初始化指令: addl $0x01, %eax

        // Insert DECAF_INSN_BEGIN callback

        movi_i32 tmp25, $DECAF_invoke_insn_begin_callback

        call tmp25, $0x0, $0, env

        movi_i32 tmp14, $0x01

        add_i32 tmp15, tmp14, tmp13

        mov_i32 eax, tmp15

        // 觸發(fā) DECAF_INSN_END 回調(diào)

        movi_i32 tmp26, $DECAF_invoke_insn_end_callback

        call tmp26, $0x0, $0, env

        // 翻譯塊結(jié)束

        // 觸發(fā) DECAF_BLOCK_END 回調(diào)

        movi_i32 tmp27, $DECAF_invoke_block_end_callback

        call tmp27, $0x0, $0, env

        goto_tb $0x0

        上面的代碼展示了輔助函數(shù)DECAF_invoke_insn_begin_callback 和 DECAF_invoke_insn_end_callback的使用,即在相應(yīng)的事件發(fā)生時(shí),這兩個(gè)函數(shù)會(huì)被插入到客戶指令的開頭和結(jié)尾。

        這里需要說明:事件對應(yīng)的回調(diào)函數(shù)調(diào)度機(jī)制的設(shè)計(jì),即對于每一個(gè)事件,例如翻譯塊開始,只能插入一個(gè)輔助函數(shù),而不能在一個(gè)事件發(fā)生時(shí),同時(shí)調(diào)用多個(gè)函數(shù)對數(shù)據(jù)進(jìn)行處理,且在輔助函數(shù)內(nèi),會(huì)遍歷為該事件注冊的所有回調(diào)函數(shù),并且決定觸發(fā)哪個(gè)。該設(shè)計(jì)有兩個(gè)理由:1)各種插件和平臺(tái)自身對于同一個(gè)事件會(huì)注冊很多回調(diào)函數(shù),重復(fù)調(diào)用這些輔助函數(shù)會(huì)對系統(tǒng)的性能產(chǎn)生負(fù)面影響。而上面設(shè)計(jì)的調(diào)度機(jī)制可以避免輔助函數(shù)的內(nèi)聯(lián)重復(fù)調(diào)用這一問題。2)在全系統(tǒng)仿真模擬器中,插入到代碼流中的回調(diào)函數(shù)會(huì)在整個(gè)客戶操作系統(tǒng)環(huán)境中執(zhí)行,例如,指令碼被插入到一個(gè)共享庫中,就會(huì)被所有使用這個(gè)庫的程序執(zhí)行。所以需要調(diào)度機(jī)制來確保當(dāng)前的執(zhí)行環(huán)境是否對每一個(gè)注冊的回調(diào)函數(shù)都是正確的,之后才可以決定執(zhí)行。

        2 實(shí)例分析

        目前的基于軟件行為的可疑軟件的分析和監(jiān)控可通過靜態(tài)分析或者動(dòng)態(tài)學(xué)習(xí),建立軟件的控制流行為模型來實(shí)現(xiàn),如統(tǒng)調(diào)用模型和函數(shù)調(diào)用模型[7-9]??刂屏餍袨槎攘磕P鸵驯蛔C明可以有效地檢測對于控制數(shù)據(jù)的攻擊[10-11],如惡意代碼注入攻擊、返回庫函數(shù)攻擊等常見的攻擊類型。在此背景下,本文從控制流的角度出發(fā),通過使用本文的監(jiān)控框架對程序的可疑性進(jìn)行分析判斷。以圖5為例,這是一個(gè)簡單的判斷輸入信息是否為數(shù)字的程序。當(dāng)程序正常運(yùn)行時(shí),即用戶從終端輸入數(shù)字的情況下,將susData賦值給memData,但是當(dāng)用戶輸入的信息不是數(shù)字時(shí),即視為程序異常,將會(huì)彈出對話框并對用戶進(jìn)行提示。

        //判斷輸入是否為數(shù)字

        1)if(susData < ‘0’ || susData > ‘9’)

        2)MessageBox(NULL, TEXT(“WRONG”), TEXT(“NOT A NUMBER”), MB_OK);

        3)else

        4)memData=susData;

        5)cout 《susData;

        圖5 程序正常運(yùn)行路徑Fig.5 Normal runtime path

        正常的運(yùn)行流程的執(zhí)行順序應(yīng)為1→3→4→5,但是當(dāng)程序異常時(shí),執(zhí)行順序則為1→2→5,造成了程序的行為異常。這是由于在節(jié)點(diǎn)1的控制信息不同引發(fā)的。因此,可以通過監(jiān)測程序的控制流信息,了解到程序是否在預(yù)期的軌跡上正常運(yùn)行,并以此為依據(jù),判斷程序的行為是否可疑。

        2.1 基于標(biāo)志寄存器的控制流信息搜集

        在執(zhí)行條件跳轉(zhuǎn)指令時(shí),匯編語言通過判斷標(biāo)志位寄存器的情況來判斷是否進(jìn)行跳轉(zhuǎn)。如匯編語言的JE指令在執(zhí)行的時(shí)候,系統(tǒng)會(huì)查詢標(biāo)志寄存器中的ZF標(biāo)志位的內(nèi)容。如果ZF=1,符合跳轉(zhuǎn)條件,則程序計(jì)數(shù)器會(huì)跳轉(zhuǎn)到目標(biāo)地址;如果ZF=0,則說明跳轉(zhuǎn)條件不成立,程序計(jì)數(shù)器將會(huì)指向緊接著的下一條指令地址,順序執(zhí)行。通過獲取在每次跳轉(zhuǎn)時(shí)的標(biāo)志位寄存器信息,加以處理整合,就可以得到程序運(yùn)行過程中的控制流信息,并確定跳轉(zhuǎn)的目的地址。這里不考慮CALL指令和JMP指令這兩個(gè)跳轉(zhuǎn)指令,因?yàn)樘D(zhuǎn)的目的地址在程序編寫時(shí)已經(jīng)確定,不受控制流信息影響。

        2.2 事件驅(qū)動(dòng)與回調(diào)函數(shù)的設(shè)計(jì)

        基于事件驅(qū)動(dòng)機(jī)制,本文設(shè)計(jì)了回調(diào)函數(shù)來收集控制流信息。由于QEMU中每一個(gè)翻譯塊對應(yīng)進(jìn)程的一條指令,因此為了獲取條件跳轉(zhuǎn)指令,對代碼塊執(zhí)行結(jié)束事件(VM_BLOCK_END_CB)進(jìn)行注冊。在事件發(fā)生時(shí),調(diào)用回調(diào)函數(shù),該函數(shù)根據(jù)DECAF提供的用戶接口,對數(shù)據(jù)進(jìn)行分析處理,完成控制流信息收集工作。

        在回調(diào)函數(shù)中,需要獲取翻譯執(zhí)行結(jié)束時(shí)的系統(tǒng)狀態(tài)、翻譯塊的信息、當(dāng)前程序計(jì)數(shù)器及下一條指令的程序計(jì)數(shù)器值。DECAF提供了DECAF_Block_End_Params數(shù)據(jù)結(jié)構(gòu),且將對這些變量的賦值過程進(jìn)行了封裝,可直接使用。

        typedef struct _DECAF_Block_End_Params

        {

        CPUState* env; //CPU環(huán)境

        TranslationBlock* tb; //翻譯塊

        gva_t cur_pc; //當(dāng)前PE值

        gva_t next_pc; //下一個(gè)PC值

        } DECAF_Block_End_Params;

        本文首先通過當(dāng)前的PC值獲取當(dāng)前指令,然后通過操作碼判斷指令類型。對于指令JE/JZ (ZF=1),其操作碼為01111110??梢酝ㄟ^操作碼判斷當(dāng)前指令是否為條件跳轉(zhuǎn)指令,如果是,繼續(xù)進(jìn)行下一步處理。由于DECAF通過QEMU提供的接口獲取CPU狀態(tài),并將CPU信息存儲(chǔ)在結(jié)構(gòu)體CPUState中,所以本文將該結(jié)構(gòu)體中的eflag的信息提取出來,并保存在記錄文件中。

        在回調(diào)函數(shù)中,首先要初始化插件,然后獲取要檢測的程序名稱和保存結(jié)果的記錄文件名稱。根據(jù)事件驅(qū)動(dòng)原理,當(dāng)有新的程序被調(diào)用的時(shí)候,判斷是否為被測程序,如果是,則開始信息獲取工作,再根據(jù)指令的操作碼判斷當(dāng)前指令是否為條件跳轉(zhuǎn)指令。如果否,則獲取虛擬機(jī)當(dāng)前的操作系統(tǒng)狀態(tài),并且保存在記錄文件中。然后,繼續(xù)按照此判斷和記錄原則監(jiān)控和跟蹤程序的動(dòng)態(tài)運(yùn)行。當(dāng)程序結(jié)束時(shí),注銷翻譯塊結(jié)束事件發(fā)生時(shí)要調(diào)用的相關(guān)函數(shù),最后清理插件資源。

        3 測試平臺(tái)部署與運(yùn)行

        3.1 測試環(huán)境構(gòu)建

        本文選用虛擬機(jī)QEMU,可以直接使用如下命令進(jìn)行QEMU安裝。

        $ sudo apt-get install qemu sudo apt-get build-dep qemu

        對于DECAF,需要安裝BFD庫和boost庫,命令如下:

        $ sudo apt-get install binutils-dev

        $ sudo apt-get install libboost-all-dev

        在準(zhǔn)備好庫后,開始進(jìn)行配置和編譯工作。DECAF有三個(gè)基本的功能設(shè)置:TCG污點(diǎn)傳播、VMI和TCG IR日志。因本文只涉及到虛擬機(jī)自省技術(shù)(virtual machine instropection,VMI),所以只啟用這一功能。然后進(jìn)行編譯,QEMU就可以運(yùn)行了,指令如下:

        $ sudo config make install

        完成QEMU的安裝之后,就可以開始在其上安裝操作系統(tǒng)鏡像,創(chuàng)建所需使用的虛擬機(jī)。雖然QEMU本身已經(jīng)幾乎和任何運(yùn)行x86體系結(jié)構(gòu)的客戶操作系統(tǒng)兼容,然而DECAF需要更多關(guān)于操作系統(tǒng)的信息,進(jìn)行語義翻譯,提供更多諸如進(jìn)程的操作系統(tǒng)抽象信息,所以從打開虛擬機(jī)開始,使用DECAF控制QEMU運(yùn)行。

        鏡像準(zhǔn)備好之后,可以加載QCOW格式的鏡像到QEMU中,完成虛擬機(jī)的創(chuàng)建。接下來,通過終端啟動(dòng)QEMU并運(yùn)行虛擬機(jī),QEMU窗口就會(huì)彈出,可以看到虛擬機(jī)啟動(dòng)情況。

        3.2 控制流信息獲取過程

        3.2.1 注冊關(guān)注事件

        根據(jù)DECAF的事件驅(qū)動(dòng)機(jī)制,用戶可選擇所關(guān)注的事件進(jìn)行注冊,并根據(jù)這個(gè)事件的發(fā)生,獲取系統(tǒng)信息,進(jìn)行相應(yīng)的處理與分析。首先通過如下命令注冊新進(jìn)程開始事件:handle_load_mainmodule=VMI_register_callback(VMI_CREATEPROC_CB,ProcessTrace_loadmainmodule_notify,&should_monitor);

        同樣地,在被測程序關(guān)閉后,監(jiān)控工作也應(yīng)該自動(dòng)結(jié)束,并且對注冊的時(shí)間關(guān)聯(lián)函數(shù)進(jìn)行注銷,實(shí)現(xiàn)代碼如下:

        handle_remov_process=VMI_register_callback(VMI_REMOVEPROC_CB,ProcessTrace_procexit,&should_monitor);

        當(dāng)新的進(jìn)程開始運(yùn)行這一事件發(fā)生后,所需要進(jìn)行的操作如下。首先需要判斷新開始運(yùn)行的這個(gè)進(jìn)程是否為被測進(jìn)程,這可以通過獲取QEMU當(dāng)前系統(tǒng)環(huán)境信息實(shí)現(xiàn)。具體數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:

        typedef struct _VMI_CreateProc_Params {

        uint32_t pid; //新進(jìn)程PID

        uint32_t cr3; //新進(jìn)程CR3

        char *name; //新進(jìn)程名稱

        }VMI_CreateProc_Params;

        將當(dāng)前程序的名稱與被檢測的進(jìn)程名稱進(jìn)行對比,如calc.exe。判斷當(dāng)前程序的名稱是否與用戶輸入的要監(jiān)控的進(jìn)程名稱一致。如果不一致,繼續(xù)等待下一個(gè)新進(jìn)程被運(yùn)行;如果一致,首先在終端輸出,告知用戶被監(jiān)控程序已經(jīng)開始。

        程序運(yùn)行后,系統(tǒng)會(huì)為程序分配一個(gè)進(jìn)程PID,并根據(jù)當(dāng)前程序運(yùn)行情況,將被測程序的PID存入到被測程序的數(shù)據(jù)結(jié)構(gòu)中。同樣,將CR3寄存器的內(nèi)容進(jìn)行保存。根據(jù)以上需求,被監(jiān)控程序需要采用如下數(shù)據(jù)結(jié)構(gòu)來保存相關(guān)信息。

        struct monitored_proc {

        char name[512]; //被測進(jìn)程名稱

        char configfile[512];//編譯文件

        uint32_t cr3; //被測進(jìn)程CR3

        uint32_t pid; //被測進(jìn)程PID

        FILE *tracefile; //記錄文件地址

        };

        接下來,注冊事件發(fā)生時(shí)要調(diào)用的相關(guān)函數(shù),DECAF_registerOptimizedBlockEndCallback,具體實(shí)現(xiàn)方法如下:

        static void

        ProcessTrace_loadmainmodule_notify(VMI_Callback_Params *pcp)

        { char *errorstring;

        int i;

        uint32_t pid=pcp->cp.pid; //獲取進(jìn)程的id

        char *name=pcp->cp.name; //獲取進(jìn)程的名稱

        if(strlen(mon_proc.name) > 0)

        { //檢查目標(biāo)進(jìn)程的名稱是否有效

        if(strcmp(mon_proc.name, name)==0)

        { //創(chuàng)建的進(jìn)程名稱與目標(biāo)進(jìn)程名稱一致

        printf("%s is starting! ",mon_proc.name);

        //輸出目標(biāo)進(jìn)程開始執(zhí)行的信息

        mon_proc.pid=pid; //設(shè)置目標(biāo)進(jìn)程的id

        mon_proc.cr3=VMI_find_cr3_by_pid_c(pid);

        //設(shè)置目標(biāo)進(jìn)程的cr3

        / / 進(jìn)行開始執(zhí)行, 注冊回調(diào)函數(shù)

        if (!handle_block_end)

        //注冊block end事件,開始對進(jìn)程的控制流進(jìn)行監(jiān)控和收集

        handle_block_end=

        DECAF_registerOptimizedBlockEndCallback(do_block_end, NULL, INV_ADDR,INV_ADDR);

        }

        }

        }

        相應(yīng)地,在被測程序關(guān)閉后,需要注銷已經(jīng)注冊的事件。首先,在終端提示用戶被監(jiān)控進(jìn)程已關(guān)閉,監(jiān)控任務(wù)結(jié)束后,關(guān)閉記錄文件;然后清空被監(jiān)控程序的數(shù)據(jù)結(jié)構(gòu)中對應(yīng)的相應(yīng)數(shù)據(jù),最后利用DECAF提供的指令完成事件注銷。具體代碼如下:

        int i=0;

        uint32_t pid=pcp->rp.pid; //被刪除進(jìn)程Pid

        if(pid==mon_proc.pid) { //如果是被測進(jìn)程

        //輸出相關(guān)信息

        printf("%s is closed. ", mon_proc.name);

        printf("%d kernel calls found. ", kcount);

        //關(guān)閉文件

        fclose(mon_proc.tracefile);

        mon_proc.tracefile=NULL;

        if (handle_block_end) //如果有回調(diào)函數(shù)

        DECAF_unregisterOptimizedBlockEndCallback(handle_block_end); //注銷

        }

        3.2.2 判斷獲取時(shí)機(jī)

        確定被監(jiān)測程序之后,可以開始控制流信息的獲取。當(dāng)翻譯塊執(zhí)行結(jié)束這一事件發(fā)生時(shí),可以獲取到當(dāng)前指令內(nèi)容。首先通過當(dāng)前系統(tǒng)的環(huán)境變量參數(shù)來判斷系統(tǒng)是否處于內(nèi)核態(tài),如果是內(nèi)核態(tài),則說明正在執(zhí)行內(nèi)核相關(guān)的系統(tǒng)調(diào)用指令,不需要進(jìn)行分析處理,直接返回,等待下一個(gè)關(guān)注事件發(fā)生。 DECAF提供了一個(gè)回調(diào)函數(shù)聯(lián)合體,根據(jù)不同的事件,提供不同的參數(shù)。聯(lián)合體的數(shù)據(jù)結(jié)構(gòu)如下:

        typedef struct _DECAF_Callback_Params

        {

        DECAF_Handle cbhandle;

        union{

        DECAF_Block_Begin_Params bb;

        DECAF_Block_End_Params be;

        DECAF_Insn_Begin_Params ib;

        DECAF_Insn_End_Params ie;

        DECAF_Mem_Read_Params mr;

        DECAF_Mem_Write_Params mw;

        DECAF_EIP_Check_Params ec;

        DECAF_Keystroke_Params ks;

        DECAF_Nic_Rec_Params nr;

        DECAF_Nic_Send_Params ns;

        DECAF_Opcode_Range_Params op;

        DECAF_Tlb_Exec_Params tx;

        DECAF_Read_Taint_Mem rt;

        DECAF_Write_Taint_Mem wt;

        #ifdef CONFIG_TCG_LLVM

        DECAF_Block_Trans_Params bt;

        #endif /* CONFIG_TCG_LLVM */

        };

        } DECAF_Callback_Params;

        在這部分,本文關(guān)注翻譯塊執(zhí)行結(jié)束事件,即“DECAF_Block_End_Params”這一類型。這一類型中有四個(gè)變量:當(dāng)前CPU狀態(tài)、翻譯塊指針、當(dāng)前程序PC值和下一個(gè)PC值,數(shù)據(jù)結(jié)構(gòu)如下:

        typedef struct _DECAF_Block_End_Params

        {

        CPUState* env; //CPU狀態(tài)

        TranslationBlock* tb; //翻譯塊

        gva_t cur_pc; //當(dāng)前PC

        gva_t next_pc; //下一個(gè)PC

        } DECAF_Block_End_Params;

        通過傳入第一個(gè)變量env可以利用DECAF的判斷函數(shù)判斷當(dāng)前系統(tǒng)是否處于內(nèi)核狀態(tài)。若系統(tǒng)不處于內(nèi)核態(tài),則意味著當(dāng)前指令屬于被測進(jìn)程,通過當(dāng)前PC值,獲取匯編指令對應(yīng)的指令編碼。由于本文主要關(guān)注條件跳轉(zhuǎn)指令,通過其獲取控制流信息內(nèi)容,而在Windows_x86系統(tǒng)中,編碼第一字節(jié)的內(nèi)容為指令的操作碼,可以根據(jù)操作碼判斷當(dāng)前指令是否為條件跳轉(zhuǎn)指令。

        然后,判斷當(dāng)前指令所屬的進(jìn)程是否為監(jiān)視進(jìn)程??赏ㄟ^DECAF提供的宏,獲取當(dāng)前CR3寄存器的值。因?yàn)槊恳粋€(gè)進(jìn)程都有自己的CR3寄存器內(nèi)容,所以可以根據(jù)這個(gè)值進(jìn)行判斷。如果指令不屬于被監(jiān)控程序,則直接返回,等待下一個(gè)翻譯塊執(zhí)行事件的發(fā)生。如果是被監(jiān)控進(jìn)程,則繼續(xù)下面的相關(guān)信息的提取工作。

        3.2.3 提取相關(guān)信息

        確定當(dāng)前指令是屬于被監(jiān)控程序的一條跳轉(zhuǎn)指令后,開始獲取當(dāng)前系統(tǒng)標(biāo)志位寄存器狀態(tài)的工作。在x86系統(tǒng)中,有一個(gè)32位的標(biāo)志寄存器。在初始化時(shí),x86的標(biāo)志寄存器狀態(tài)為00000002H,第1、3、5、15以及22~31位被系統(tǒng)預(yù)留,內(nèi)容固定,不表示任何具體信息,程序的運(yùn)行也不會(huì)以這些位的內(nèi)容為依據(jù)。標(biāo)志位寄存器的值不能被整體復(fù)制或修改,因?yàn)樗鼈兌际歉鶕?jù)特定指令,由系統(tǒng)進(jìn)行修改,例如cmp指令,執(zhí)行后不保留運(yùn)算結(jié)果,只對標(biāo)志寄存器產(chǎn)生影響,然后通過其他相關(guān)指令訪問這些被影響的標(biāo)志寄存器,來產(chǎn)生對整個(gè)程序的影響。但是,通過DECAF提供的接口,可以直接將標(biāo)志寄存器的信息賦值給特定類型的變量,然后將其輸出到記錄文件中。

        本文設(shè)計(jì)的獲取eflags的變量類型定義如下。因?yàn)镈ECAF支持多種體系結(jié)構(gòu)和操作系統(tǒng)的虛擬機(jī),所以根據(jù)不同的虛擬機(jī)類型,有一套對應(yīng)機(jī)制。如果是32位系統(tǒng),則將獲取eflags的變量類型定位為32位,對于64位的操作系統(tǒng)也進(jìn)行相應(yīng)的定義。

        #if TARGET_LONG_SIZE==4

        //如果目標(biāo)代碼長4字節(jié),按如下方式進(jìn)行定義

        //定義long型

        typedef int32_t target_long

        __attribute__((aligned(TARGET_LONG_ALIGNMENT)));

        //定義無符號long型

        typedef uint32_t target_ulong

        __attribute__((aligned(TARGET_LONG_ALIGNMENT)));

        //定義lx

        #define TARGET_FMT_lx "%08x"

        //定義ld

        #define TARGET_FMT_ld "%d"

        //定義lu

        #define TARGET_FMT_lu "%u"

        #elif TARGET_LONG_SIZE==8

        //如果目標(biāo)代碼長8字節(jié),按如下方式進(jìn)行定義

        typedef int64_t target_long

        __attribute__((aligned(TARGET_LONG_ALIGNMENT)));

        typedef uint64_t target_ulong

        __attribute__((aligned(TARGET_LONG_ALIGNMENT)));

        #define TARGET_FMT_lx "%016" /*PRIx64*/

        #define TARGET_FMT_ld "%" PRId64

        #define TARGET_FMT_lu "%" PRIu64

        #else

        #error TARGET_LONG_SIZE undefined

        #endif

        3.3 封裝功能

        通過以上過程得到了程序動(dòng)態(tài)運(yùn)行過程中的控制流信息。下面需要對功能進(jìn)行封裝,完成與DECAF平臺(tái)接口的連接工作和用戶交互的實(shí)現(xiàn)。

        用戶使用本項(xiàng)目所提供的功能時(shí),需要在命令行輸入如下命令:

        trace_process process_name trace_file_name

        其中,包含兩個(gè)參數(shù):進(jìn)程名和記錄文件名稱。

        在Linux中,通過定義命令配置文件,將實(shí)現(xiàn)功能的函數(shù)與命令綁定。具體來說,當(dāng)用戶在終端輸入trace_process命令時(shí),調(diào)用do_trace_process()函數(shù)。實(shí)現(xiàn)代碼如下:

        {//命令名稱

        .name=“trace_process”,

        //命令類型

        .args_type="proc_name:s,tracefile:F",

        //命令處理函數(shù)

        .mhandler.cmd=do_trace_process,

        //記錄文件

        .params=“process_name trace_file_name”,

        //使用說明

        .help="Trace by name of the process. The process must not have started yet. The trace is saved to the said file.",

        }

        然后,do_trace_process()函數(shù)從命令行提取參數(shù),具體實(shí)現(xiàn)代碼如下:

        //獲取進(jìn)程名稱

        const char *procname=qdict_get_str(qdict,

        “proc_name”);

        //獲取記錄文件路徑

        const char *tracefile_path=qdict_get_str(qdict, “tracefile”);

        存放被監(jiān)測程序信息的結(jié)構(gòu)體設(shè)計(jì)如下。

        struct monitored_proc {

        char name[512]; //進(jìn)程名稱

        char configfile[512]; //配置文件

        uint32_t cr3; //CR3寄存器

        uint32_t pid; //進(jìn)程ID

        FILE *tracefile; } //記錄文件

        首先,命令的參數(shù)中,用戶輸入的被測程序的名字記錄到結(jié)構(gòu)體對應(yīng)的變量中;然后,根據(jù)用戶輸入的記錄文件路徑嘗試打開文件,如果路徑無效或者文件無法打開,則在終端給用戶提示,不進(jìn)行后續(xù)工作。該處理可以增強(qiáng)程序的健壯性。如果文件可以成功打開,則將記錄文件路徑寫入結(jié)構(gòu)體,然后等待被測程序運(yùn)行,并通過終端告知用戶程序開始運(yùn)行。

        下面是Linux命令處理模塊的部分代碼。模塊的輸入信息為被測程序和記錄文件。

        int i;

        FILE *tracefile;

        //新建進(jìn)程如果是被測進(jìn)程

        if(strcmp(mon_proc.name, procname)==0) {

        printf("Process %s already being traced. ", procname);

        return;

        }

        //保存被測進(jìn)程名稱

        strncpy(mon_proc.name, procname, 512);

        mon_proc.name[511]='

        日本a一区二区三区在线| 中国xxx农村性视频| 久久精品国产精品亚洲毛片| 久久国产香蕉一区精品天美| 亚洲av色香蕉一区二区三区潮| 精品+无码+在线观看| 色伦专区97中文字幕| 国产精品av在线一区二区三区 | 在线观看日韩精品视频网站| 国产av精品一区二区三区久久| 亚洲avav天堂av在线网毛片| 欧美视频在线观看一区二区| 久久久国产视频久久久| 日本女优在线一区二区三区| 黑人巨大跨种族video| 中文字幕久无码免费久久| 一区两区三区视频在线观看| 国产极品美女高潮无套| 骚小妹影院| 午夜久久精品国产亚洲av| 日本办公室三级在线观看| 玩弄放荡人妇系列av在线网站| 精品久久久久久久中文字幕| 久久久精品国产视频在线| 99在线视频这里只有精品伊人| wwww亚洲熟妇久久久久| 国产成人精品三级麻豆| 日本一本二本三本道久久久| 国产精品午夜福利视频234区 | 一本久道视频无线视频试看| 中字乱码视频| 亚洲视频一区| 国产欧美日本亚洲精品一5区| 日韩中文字幕素人水野一区 | 午夜福利电影| 国产好片日本一区二区三区四区| 日本免费一区二区在线视频播放| 亚洲av无码一区二区乱孑伦as| 国产一区二区三区啪| 国产一区二区在线中文字幕| 色一情一乱一伦一视频免费看|