輔助下能夠減少在敏感操作無關(guān)路徑上消耗的計算時間和資源,提高符號執(zhí)行漏洞檢測的效率,進(jìn)一步地,在有限的時間和計算資源情況下檢測到更多潛在漏洞。
【附圖說明】
[0020]圖1為靜態(tài)分析輔助的符號執(zhí)行漏洞檢測方法總體流程圖;
[0021]圖2為程序模塊預(yù)處理流程圖;
[0022]圖3為敏感相關(guān)函數(shù)識別流程圖;
[0023]圖4為敏感導(dǎo)向函數(shù)識別流程圖;
[0024]圖5為有效跳轉(zhuǎn)收集流程圖;
[0025]圖6為分支打分流程圖;
[0026]圖7為漏洞檢測符號執(zhí)行流程圖;
[0027]圖8為指令執(zhí)行流程圖。
【具體實施方式】
[0028]圖1所示為本方法的總體流程圖。本方法的輸入分為兩部分:目標(biāo)程序字節(jié)碼與配置文件。目標(biāo)程序字節(jié)碼通過LLVM 3.1編譯器體系的前端Clang編譯C/C++源程序獲得。用戶可以在配置文件中定義可能產(chǎn)生軟件漏洞的敏感操作作為本次檢測的目標(biāo),并且為每個敏感操作定義相應(yīng)的安全約束。如果在所處的執(zhí)行環(huán)境下敏感操作能夠違反安全約束,則該敏感操作被認(rèn)為是可觸發(fā)的程序漏洞。本方法的輸出是程序輸入的測試樣例,通過執(zhí)行該測試樣例,能夠到達(dá)當(dāng)前執(zhí)行環(huán)境并觸發(fā)敏感操作使其違反安全約束。
[0029]首先,輕量級符號執(zhí)行過程使用符號執(zhí)行工具KLEE對目標(biāo)程序字節(jié)碼進(jìn)行符號執(zhí)行得到鏈接后的完整程序字節(jié)碼,符號化策略為:-sym-args I I 2,即I個長度為I個字節(jié)的符號作為程序輸入。之后,圖生成階段在完整程序字節(jié)碼的基礎(chǔ)上使用LLVM 3.1工具集的opt工具生成完整程序的函數(shù)調(diào)用圖與各個函數(shù)的控制流圖,生成的函數(shù)調(diào)用圖中包括兩類語句:函數(shù)描述語句與函數(shù)調(diào)用關(guān)系描述語句。函數(shù)描述語句中包括了函數(shù)調(diào)用圖中出現(xiàn)的所有函數(shù)的函數(shù)名與函數(shù)編號;函數(shù)調(diào)用關(guān)系描述語句則描述了所有函數(shù)之間的調(diào)用關(guān)系。函數(shù)的控制流圖中包含兩類語句:基本塊描述語句與基本塊間關(guān)系描述語句。基本塊描述語句描述了函數(shù)中每個基本塊的基本塊編號,基本塊標(biāo)簽和基本塊包含的指令,特別地,如果該基本塊的最后一條語句是條件分支指令,基本塊描述語句中還會包含跳轉(zhuǎn)到各個分支的條件取值;基本塊間關(guān)系描述語句則描述了所有基本塊之間的前驅(qū)與后繼關(guān)系。然后,在靜態(tài)分析過程中,通過程序模塊預(yù)處理過程得到靜態(tài)分析的對象,并通過函數(shù)標(biāo)記、有效跳轉(zhuǎn)收集和分支打分過程,獲得有效跳轉(zhuǎn)表與分支打分表。最后,在符號執(zhí)行過程中使用有效跳轉(zhuǎn)表與分支打分表輔助漏洞檢測符號執(zhí)行。在具體實施中,符號執(zhí)行部分在KLEE符號執(zhí)行工具的基礎(chǔ)上在指令執(zhí)行過程中添加了靜態(tài)輔助方法并增加了基于后續(xù)子程序中敏感操作相關(guān)路徑比例的分支選擇過程。當(dāng)檢測到敏感操作時,使用約束求解器STP求解當(dāng)前執(zhí)行環(huán)境下敏感操作能否違反安全約束,如果有解,則表示該敏感操作是可利用的安全漏洞,返回對應(yīng)的測試樣例給用戶。
[0030]圖2為程序模塊預(yù)處理流程圖。以完整程序的函數(shù)調(diào)用圖和控制流圖為輸入,預(yù)處理靜態(tài)分析中的程序模塊,靜態(tài)分析中后續(xù)的函數(shù)識別、有效跳轉(zhuǎn)收集和分支打分都是在程序模塊的基礎(chǔ)上分析得到的。使用程序模塊來表示當(dāng)前正在靜態(tài)分析的程序。程序模塊中包括如下數(shù)據(jù)結(jié)構(gòu):函數(shù)鏈表,以鏈表的形式存儲了該程序模塊中所有函數(shù)的指針;敏感相關(guān)函數(shù)鏈表,以鏈表的形式存儲了程序模塊中所有被標(biāo)記為敏感相關(guān)的函數(shù)的指針;敏感導(dǎo)向函數(shù)鏈表,以鏈表的形式存儲了程序模塊中所有被標(biāo)記為敏感導(dǎo)向的函數(shù)的指針;有效跳轉(zhuǎn)表,以集合的形式存儲了函數(shù)模塊中的有效跳轉(zhuǎn),集合中的元組〈funct1n, instruct1n, condit1n)表不指令 instruct1n 是函數(shù) funct1n 中的分支指令,且如果分支條件取值為condit1n就能夠?qū)蛎舾胁僮?;分支分?jǐn)?shù)表,以哈希表的形式存儲了程序模塊中分支的分?jǐn)?shù),表中元組〈funct1n, instruct1n, score〉表示指令instruct1n是函數(shù)funct1n中某個基本塊的起始指令且以該指令為起始指令的分支分?jǐn)?shù)為score ;目標(biāo)操作集合,以集合的形式存儲檢測過程中的目標(biāo)操作;敏感操作及安全約束表,以哈希表的形式存儲用戶定義的敏感操作和每個敏感操作對應(yīng)的安全約束,如果在所處的執(zhí)行環(huán)境下敏感操作能夠違反安全約束,則該敏感操作被認(rèn)為是可觸發(fā)的程序漏洞。對于程序模塊中的函數(shù),包含如下數(shù)據(jù)結(jié)構(gòu):函數(shù)名;函數(shù)編號;調(diào)用者函數(shù)鏈表,以鏈表的形式存儲所有調(diào)用該函數(shù)的函數(shù)指針;調(diào)用函數(shù)鏈表,以鏈表的形式存儲所有被該函數(shù)調(diào)用的函數(shù)的指針;基本塊鏈表,以鏈表的形式存儲該函數(shù)中基本塊的指針。函數(shù)中的基本塊,包含如下的數(shù)據(jù)結(jié)構(gòu):基本塊編號;基本塊標(biāo)簽;指令鏈表,以鏈表的形式存儲基本塊中的指令;前驅(qū)基本塊鏈表,以鏈表的形式存儲該基本塊所有前驅(qū)基本塊的指針;后繼基本塊鏈表,以鏈表的形式存儲該基本塊所有的后繼基本塊指針。
[0031]步驟20是初始動作。步驟21模塊預(yù)處理:設(shè)置模塊的函數(shù)鏈表、敏感相關(guān)函數(shù)鏈表、敏感導(dǎo)向函數(shù)鏈表為空鏈表,初始化有效跳轉(zhuǎn)表為空集合,初始化分支打分表為空哈希表。步驟22函數(shù)預(yù)處理:讀入函數(shù)調(diào)用圖,按函數(shù)描述語句設(shè)置函數(shù)名、函數(shù)編號;按照函數(shù)調(diào)用關(guān)系語句設(shè)置調(diào)用者函數(shù)鏈表與調(diào)用函數(shù)鏈表;設(shè)置函數(shù)為非敏感相關(guān)、非敏感導(dǎo)向并將基本塊鏈表初始化為空鏈表;將初始化完成的函數(shù)添加到函數(shù)鏈表中。步驟23設(shè)置循環(huán)起始條件,取函數(shù)鏈表中的第一個函數(shù)為當(dāng)前函數(shù)。步驟24判斷當(dāng)前函數(shù)是否為空,若為空,全部函數(shù)基本塊預(yù)處理完成,跳轉(zhuǎn)到步驟29,循環(huán)結(jié)束;否則跳轉(zhuǎn)到步驟25,進(jìn)入循環(huán)。步驟25判斷圖生成階段生成的各個函數(shù)的控制流圖集合中是否存在當(dāng)前函數(shù)的控制流圖,如果存在,表示當(dāng)前函數(shù)在程序的字節(jié)碼中有函數(shù)定義,跳轉(zhuǎn)到步驟26 ;否則當(dāng)前函數(shù)在字節(jié)碼中僅僅是函數(shù)聲明,跳轉(zhuǎn)到步驟27。步驟26定義函數(shù)基本塊預(yù)處理:將當(dāng)前函數(shù)標(biāo)記為定義函數(shù),讀取當(dāng)前函數(shù)的控制流圖,按照控制流圖中的基本塊描述語句初始化基本塊的基本塊編號和基本塊標(biāo)簽,按照基本塊間關(guān)系描述語句初始化基本塊的前驅(qū)基本塊鏈表與后繼基本塊鏈表,然后將基本塊設(shè)置為非敏感操作相關(guān),最后將基本塊添加到當(dāng)前函數(shù)的基本塊鏈表中,跳轉(zhuǎn)到步驟28。步驟27聲明函數(shù)基本塊預(yù)處理:將函數(shù)標(biāo)記為聲明函數(shù),并將對該函數(shù)的調(diào)用操作添加到目標(biāo)操作集合中。步驟28取函數(shù)鏈表中的下一個函數(shù)為當(dāng)前函數(shù),跳轉(zhuǎn)到步驟25。29敏感操作預(yù)處理:讀取配置文件,將用戶定義的敏感操作添加到目標(biāo)操作集合中,將用戶定義的敏感操作與對應(yīng)的安全約束添加到敏感操作及安全約束表中。步驟2a是結(jié)束狀態(tài)。
[0032]圖3為敏感相關(guān)函數(shù)識別流程圖。步驟30是初始動作。步驟31設(shè)置循環(huán)起始狀態(tài),取函數(shù)鏈表中第一個函數(shù)作為當(dāng)前函數(shù)。步驟32判斷當(dāng)前函數(shù)是否為空,若是,包含目標(biāo)操作的敏感相關(guān)函數(shù)識別完成,跳轉(zhuǎn)到步驟36,循環(huán)結(jié)束;否則跳轉(zhuǎn)到步驟33,進(jìn)入循環(huán)。步驟33判斷當(dāng)前函數(shù)是否包含目標(biāo)操作集合中的操作,若包含,轉(zhuǎn)步驟34,否則跳轉(zhuǎn)到步驟35。步驟34標(biāo)記當(dāng)前函數(shù)為敏感相關(guān)并將當(dāng)前函數(shù)加入待擴(kuò)展函數(shù)集合中。步驟35取函數(shù)鏈表中下一個函數(shù)為當(dāng)前函數(shù),跳轉(zhuǎn)到步驟32。步驟36判斷待擴(kuò)展函數(shù)集合是否為空,若是,敏感相關(guān)函數(shù)擴(kuò)展完成,跳轉(zhuǎn)到步驟3d,循環(huán)結(jié)束;否則轉(zhuǎn)步驟37,進(jìn)入循環(huán)。步驟37從待擴(kuò)展函數(shù)集合中取一個函數(shù)為當(dāng)前函數(shù),并從集合中移除該函數(shù)。步驟38判斷當(dāng)前函數(shù)是否被擴(kuò)展過,若是,跳轉(zhuǎn)到步驟36,否則跳轉(zhuǎn)到步驟39。步驟39將當(dāng)前函數(shù)標(biāo)記為被擴(kuò)展過,設(shè)置循環(huán)起始狀態(tài),取當(dāng)前函數(shù)的調(diào)用者函數(shù)鏈表中第一個函數(shù)作為擴(kuò)展函數(shù)。步驟3a判斷擴(kuò)展函數(shù)是否為空,若是,轉(zhuǎn)步驟36,結(jié)束循環(huán);否則跳轉(zhuǎn)到步驟3b,進(jìn)入循環(huán)。步驟3b判斷擴(kuò)展函數(shù)是否被擴(kuò)展過,若是,轉(zhuǎn)步驟3d;否則跳轉(zhuǎn)到步驟3c。步驟3c設(shè)置擴(kuò)展函數(shù)為敏感相關(guān),并將它添加到待擴(kuò)展函數(shù)集合和敏感相關(guān)函數(shù)鏈表中。步驟3d取調(diào)用者函數(shù)鏈表的下一個函數(shù)為擴(kuò)展函數(shù),跳轉(zhuǎn)到步驟3a。步驟3e是結(jié)束狀態(tài)。
[0033]圖4為敏感導(dǎo)向函數(shù)識別流程圖。步驟40是起始動作。步驟41設(shè)置循環(huán)初始狀態(tài),取敏感相關(guān)函數(shù)鏈表中第一個函數(shù)為當(dāng)前函數(shù)。步驟42判斷當(dāng)前函數(shù)是否為空,若為空,跳轉(zhuǎn)到步驟4d;否則跳轉(zhuǎn)到步驟43,進(jìn)入循環(huán)。步驟43在當(dāng)前函數(shù)中收集目標(biāo)操作集合中目標(biāo)操作的位置到目標(biāo)操作位置集合。步驟44判斷目標(biāo)操作位置集合是否為空,若是,轉(zhuǎn)步驟4c,循環(huán)結(jié)束;否則轉(zhuǎn)步驟45,進(jìn)入循環(huán)。步驟45從目標(biāo)操作位置集合中取一個目標(biāo)操作位