代培武,潘祖烈,施 凡
國防科技大學 電子對抗學院,合肥 230000
互聯(lián)網(wǎng)的普及給人們帶來便利,惠及人們生活的各行各業(yè),但近些年發(fā)生的震網(wǎng)病毒、勒索病毒、棱鏡門事件等使人們意識到互聯(lián)網(wǎng)安全的重要性,軟件漏洞分析研究是計算機領域的熱點難點問題[1]。Fuzzing 技術通過自動或半自動的方法反復驅動目標軟件運行并為其提供構造的輸入數(shù)據(jù),同時監(jiān)控軟件運行的異常結果,能高效地產(chǎn)生Crash(程序異?;虮罎ⅲ2],但該方法存在盲目性,產(chǎn)生的Crash數(shù)量巨大,只有極少數(shù)與漏洞成因有關,逐個分析會耗費研究人員大量時間,效率低下卻錯誤率較高。因此如何自動化地對Crash進行分類和精簡是漏洞研究人員急需攻克的難題。
在早期的軟件安全研究過程中,研究人員借助OllyDbg和C32Asm等調試器對二進制代碼的整體結構和模塊進行手工分析,并在可知的執(zhí)行路徑上進行相應的實際跟蹤,這嚴重依賴分析人員的技術水平和經(jīng)驗能力,誤判率較高。后來開發(fā)的Valgrind[3]、AddressSanitizer[4]等一些低級的內存檢測工具通過錯誤路徑修改、增量分析、SAT 分析來發(fā)現(xiàn)導致系統(tǒng)崩潰的內存錯誤、邏輯錯誤、指針錯誤等,但同樣存在效率和準確率的問題。動態(tài)污點分析(Dynamic Taint Analysis)[5]通過標記非信任數(shù)據(jù)來源,追蹤并記錄程序執(zhí)行過程中污點信息,檢測污點數(shù)據(jù)的非法使用,以達到獲取關鍵位置與輸入數(shù)據(jù)關聯(lián)信息的分析方法。2014年IEEE會議上,Zhang等人提出新型的二進制可執(zhí)行程序崩潰分析框架ExpTracer[6]。該框架在二進制插樁平臺Pin 上進行開發(fā),使用基于污點分析的數(shù)據(jù)流引導分析技術直接對二進制可執(zhí)行程序進行分析,能夠識別二進制可執(zhí)行程序潛在的漏洞并對Crash 進行分類和可利用性判定,但效率低下。UC Berkely大學開發(fā)的BitBlaze[7]能通過二進制可執(zhí)行程序污點分析來確定程序崩潰時哪些寄存器和內存地址來自攻擊者控制的輸入文件,對NULL指針切片的同時查看指針起始位置來快速判定二進制可執(zhí)行程序存在的漏洞類型和該Crash 是由何種類型漏洞引起的,但分析對象單一,只能對棧溢出進行分析。李根等人研發(fā)的Hunter[8]和Wang 等人開發(fā)的TaintScope[9]利用污點類型和污點虛擬化技術對二進制可執(zhí)行程序進行漏洞檢測,但無法分析Crash。
本文主要研究如何利用污點分析技術,判定二進制可執(zhí)行程序Crash 所屬漏洞類型的問題,通過結合動態(tài)污點分析方法,修改污點傳播規(guī)則,添加多種指令類型、寄存器和關鍵函數(shù)傳播約束和檢測方法,通過對常見緩沖區(qū)溢出漏洞崩潰觸發(fā)特征編寫觸發(fā)規(guī)則,在污點檢測階段提出面向漏洞類型的污點檢查點設置技術,旨在解決自動化判定Crash的所屬漏洞類型的問題。
二進制代碼翻譯(Binary Translation)[10]是將二進制可執(zhí)行程序翻譯成另外一種指令集形式,二進制代碼翻譯是安全領域研究的熱點問題,廣泛應用于代碼移植、代碼優(yōu)化、模擬器、虛擬化等方面。二進制代碼翻譯有兩種方法,分別是基于直接指令和基于中間語言,直接指令翻譯如圖1 所示:Source instruction 表示源ISA,它被二進制翻譯器翻譯為目標Target instruction。翻譯過程中可以進行各種處理,如代碼優(yōu)化和profiling等?;谥苯又噶畹亩M制代碼翻譯能夠有效處理給定的源和目標指令,適合小型的二進制可執(zhí)行程序,當程序較大或需要一致性較高的翻譯器時,該方法會顯得極其復雜。
圖1 直接指令翻譯流程
基于中間語言的方法將二進制可執(zhí)行程序翻譯成中間語言[11](Intermediate Representation,IR),IR是一種通用的表示形式,和平臺無關。圖2是采用中間語言的二進制程序翻譯流程,只需要將二進制可執(zhí)行程序翻譯成對應的IR,而后通過不同架構轉換規(guī)則進行解讀和匹配,IR適用于大型程序的分析和指令轉換,對一些規(guī)模較小的二進制程序則顯得效率低下[12]。例如,以下代碼是add eax,ebx指令的Vex表示:
圖2 中間語言二進制代碼翻譯流程
動態(tài)污點分析將非信任來源數(shù)據(jù)標記為污點,通過污點標記、污點傳播、檢測及策略匹配等階段來準確獲取程序的執(zhí)行過程[13]。動態(tài)污點傳播一般采用虛擬執(zhí)行或動態(tài)二進制插樁方式對污點數(shù)據(jù)進行記錄和跟蹤。動態(tài)二進制插樁指的是在程序運行的過程中插入自定義代碼,監(jiān)控程序運行狀態(tài),獲取程序運行時狀態(tài)信息,從而對程序進行分析的過程。Intel 公司開發(fā)的Pin插樁工具是最近幾年比較流行的插樁框架,Pin的基本思路是JIT 編譯并插入插樁代碼,同時進行優(yōu)化處理以取得較高效率[14]。Pin 由幾部分組成:虛擬機VM、Code Cache(指令緩存)、插樁API,內部架構如圖3所示。
VM包括JIT編譯器、Emulator和Dispatcher。JIT編譯插樁目標程序代碼,由Dispatcher執(zhí)行。被編譯/插樁的機器指令放入指令緩存,以便后來執(zhí)行的代碼無需編譯就可直接執(zhí)行。Emulator模擬無法由JIT編譯的機器代碼,通常用于處理系統(tǒng)調用。選擇Pin 作為插樁開發(fā)框架主要有以下優(yōu)勢[15]。
圖3 Pin插樁平臺系統(tǒng)架構
(1)普適性的插樁機制:使用動態(tài)二進制插樁,不需要源代碼和重編譯。而論文所針對的目標程序正好是沒有開放源代碼的二進制可執(zhí)行程序/軟件,采用Pin是非常有效。
(2)簡單容易的自定制,其自身包含了一套豐富的API編程接口,使得開發(fā)人員可以在現(xiàn)有Pintool的基礎上進行改進或者創(chuàng)建新的具有特定功能的Pintool。
(3)多平臺的支持:支持x86、x86-64、Itanium、Xscale的體系架構以及支持Linux、Windows、MacOS操作系統(tǒng)。
(4)健壯性和穩(wěn)定性,能夠對多種商業(yè)級的軟件進行插樁,包括數(shù)據(jù)庫、瀏覽器等;能夠對多線程程序進行插樁。
(5)高效性:提供對插樁代碼的編譯優(yōu)化。
Pin提供判斷操作數(shù)類型的API為:
INS_OperandIsMemory(ins,1) // ins是指令,
INS_OperandIsReg(ins,1)// 1 表示源操作數(shù),0 表示目的操作數(shù)
插樁指令的核心函數(shù)原型如下:
INS_InsertCall(ins,
IPOINT_BEFORE,
analysis_function,
… //多個參數(shù)
IARG_INT
第一個參數(shù)是指令,第二個參數(shù)是插樁時刻,IPOINT_BEFORE是指令執(zhí)行前插樁,IPOINT_AFTER是指令執(zhí)行后插樁,第三個參數(shù)是用戶插樁分析例程,省略號表示多個參數(shù)(直到IARG_END 結束),這些參數(shù)都是分析例程的實參。
污點分析的首要任務是識別污點源,將不可信輸入標記為污點。二進制可執(zhí)行程序Fuzz 出的Crash 本身就是一種二進制形式的輸入文件,這里認為Crash 就是污點源。為標注污點源需截獲相關函數(shù),它有若干種方法實現(xiàn):(1)驅動程序,這種方法最徹底但編寫難度較大且不穩(wěn)定;(2)通過API截獲工具如Detours實現(xiàn)。這兩種方法的共同缺點在于需要與動態(tài)插樁工具交互,而Pin目前不支持與外部程序的IPC。動態(tài)插樁工具Pin提供了系統(tǒng)調用插樁,通過Pin 提供的API 可以方便獲取參數(shù)和返回值等信息,這里采用MANGO[16]插樁socket、recv、open、read 等系統(tǒng)調用標記污點屬性,然后在執(zhí)行類似GET/PUT或LOAD/STORE之類的指令時對污點的傳播和刪除情況進行污點標記。污點標記的過程如下。
第一步:平臺捕獲sys_read 系統(tǒng)調用。通過Pin 可以初始化回調函數(shù)在系統(tǒng)調用出現(xiàn)前后添加自定義代碼進行動態(tài)插樁獲取運行時信息,采用的污點跟蹤技術粒度為字節(jié),接受外部輸入數(shù)據(jù)首先到達緩沖區(qū),對長度為buffLen 的讀入數(shù)據(jù)進行污點標注,污點表初始化偽代碼如下所示:
TaintNOdeTable(buffer,buffLen)
fori← 0 to buffLen?1 do
//將地址 buffer+i插入到 taint_table 表中,taint_table為Hash表
call taint_table_mem_insert(taint_table,buffer+i)
//地址buffer+i的污點標簽為
taint_table_mem_add_tag(taint_table,buffer+i,taint_count,i+1)
taint_count←taint_count+1
第二步:獲取這部分內存區(qū)域的相鄰后續(xù)參數(shù)。當出現(xiàn)系統(tǒng)調用時,通過調用LEVEL_PINCLIENT::PIN_AddSyscallEntryFunction函數(shù)來檢查該塊內存區(qū)域是否可讀,如果可讀則將后續(xù)參數(shù)保存,將該內存區(qū)域添加到定義好的污染字節(jié)列表中,輸出相關執(zhí)行結果。
第三步:當出現(xiàn)類似LOAD 和STORE 指令時調用處理程序。為了在受污染的內存區(qū)域中獲取LOAD/STORE所有指令,為每條指令添加一個主處理程序:
typedef VOID(*LEVEL_PINCLIENT::
INS_INSTRUMENT_CALLBACK)(INS ins,VOID *v);VOID LEVEL_PINCLIENT::
INS_AddInstrumentFunction
(INS_INSTRUMENT_CALLBACK fun,VOID * val);
污點引入通過監(jiān)控 ReadFile()、RecvFrom()、Getchar()等污點輸入函數(shù)實現(xiàn),然后在調用函數(shù)時傳遞指令地址、反匯編代碼、內存可讀區(qū)域的地址等信息[17],對STORE 類型的指令操作類似。內存地址污點污點鏈表標記如圖4所示。
Taint_tag即為污點。比如標記第一個緩沖區(qū)的第三個字節(jié),生成一個污點對象,對應的count 為1,taint_tag為3,該字節(jié)所在的內存地址經(jīng)運過算對應Memory_address_0的第二個偏移字節(jié),就將生成的污點對象插入Memory_address_0對應Taint_1鏈表中。對接受到緩沖區(qū)的每個字節(jié)進行標記,以上就是污點標記初始化的過程。
圖4 污點鏈表結構
污點跟蹤本質上是對信息流的追蹤,動態(tài)污點跟蹤階段主要考慮污點的添加和刪除,調整污點傳播策略以避免出現(xiàn)污染過度和污染缺失現(xiàn)象[18]。例如,當LOAD和STORE的對象是污點數(shù)據(jù)時,進行污點標記,當STORE的目標是常量時,由于無法控制,需要進行污點清除。這里將對特定地址進行標記而不是將某一整塊內存標記為污點屬性[19],使用std::list
設計污點傳播算法偽代碼如下所示:
procedure TaintNodeinit(INS ins,void*t)
switch typeof(ins)//指令傳播
case:MOV|CMOVcc|R*L|R*R|XCHG|STOS|LEA//數(shù)據(jù)移動類指令
e1=getSrcOperand(ins);e2=getDstOperand(ins);Taint(e1->e2)
case:ADD*,MUL*,SUB*,AND*XOR//運算類指令
e1=getSrcOperand(ins);e2=getDstOperand(ins);bitset*s=Union(e1,e2);
case:CMP|CMPS*//比較類指令
e1=LeftOperand(ci);e2=RightOperand(ci);bitset*s=Union(e1,e2);……
end procedure
procedure Taintpropagation(INS ins,void*t)
if(typeof(e1)==MEM(Reg)&&Mem(Reg)TaintMap[e1]!=Mem(Reg)TaintMap.end())
//根據(jù)指令語義和關鍵函數(shù)的規(guī)則進行污點傳播
TaintNode *insertnode(ins_taint,reg_taint)
end if
else if(typeof(e1)==bitset)Mem(Reg)TaintMap[e2]=bitset_copy(e1)
end else if
elseif(Mem(Reg)TaintMap[e1]!=Mem(Reg)TaintMap.end())bitset_free(Mem(Reg)TaintMap[e1])
//對如XOR等指令及一些函數(shù)進行污點清除
TaintNode *deletenode(ins_taint,reg_taint)
end if
end procedure
TaintNodeUpdate(INS ins,void*t)
//更新污點表(影子內存與寄存器的污點狀態(tài))
…
污點傳播需要建立污點源到污點操作數(shù)之間的傳播規(guī)則,具體如表1 所示,這里對x86_64 架構下污點相關指令和函數(shù)進行總結歸類[20],指令級污點傳播主要有以下幾種方式:
(1)數(shù)據(jù)移動類指令,例如mov、movb、movsz、movxz等,污點傳播規(guī)則時間將源操作數(shù)的污點標記賦給目的操作數(shù)。
(2)運算類指令,典型指令有add、sub、and、xor、shr、lhr 等,傳播規(guī)則是將源和目的操作數(shù)的污點標記賦給目的操作數(shù)。
圖5 動態(tài)污點傳播過程
表1 污點傳播指令及關鍵函數(shù)的規(guī)則說明
(3)單操作數(shù)指令,典型指令有not、push、pop 等,not傳播規(guī)則是清除操作數(shù)污點標記,pop傳播規(guī)則是將rsp內存污點信息賦給操作數(shù)。
(4)復雜尋址,典型指令如mov(base_reg,index_reg,immd),reg,傳播規(guī)則是在內存訪問時將內存地址以及基址寄存器和變址寄存器的污點標記賦給目的操作數(shù)。
對于敏感關鍵函數(shù),主要考慮strlen(char* str)、int strcmp(char*p1,char*p2)、strcat(char *p1,char*p2)、int atoi(char *str)、memset(void *m,charc,int len)、void* malloc(int len)、free(p)等函數(shù)的傳播策略。
污點表更新模塊主要是污點鏈表中污點的添加和刪除操作,通過對程序進行指令級插樁,分析指令執(zhí)行過程的污點傳播情況,需要對每條指令做出如下判斷:該指令是否是內存/寄存器操作指令?該指令是否引起污點傳播?污染表數(shù)據(jù)結構包含IN 和OUT 兩個污染表,分別為同一個block的前后污染信息集合,根據(jù)設定的傳播策略對滿足條件的指令進行taint_tag 添加和刪除,最后完成對污點表的合并更新。
污點檢查點是進行漏洞檢測和Crash類型識別的關鍵環(huán)節(jié),污點檢測主要針對已經(jīng)被標記為污染源的數(shù)據(jù)進行檢測,記錄在程序中的使用情況并通過監(jiān)控污點數(shù)據(jù)傳播信息來實現(xiàn)漏洞類型判斷等操作[21]。為完成以上目標,需要獲取二進制可執(zhí)行程序中的單個模塊中的所有關鍵函數(shù)和對應的關鍵字節(jié),為此設計三個識別模塊:關鍵函數(shù)識別模塊、函數(shù)調用跟蹤模塊、關鍵字節(jié)識別模塊。關鍵函數(shù)識別模塊需要找到插樁程序中哪些函數(shù)使用了污點數(shù)據(jù),哪些關鍵函數(shù)是漏洞觸發(fā)的高危函數(shù),例如printf函數(shù)族、atoi函數(shù)等;函數(shù)調用跟蹤模塊分析插樁程序內部的函數(shù)調用關系,明確正在執(zhí)行的指令屬于該模塊內的哪個函數(shù);關鍵字節(jié)識別模塊分析插樁程序指令所使用的關鍵字節(jié)。當某條指令使用了污染數(shù)據(jù),通過關鍵字節(jié)識別模塊可獲得相關的關鍵字節(jié),通過函數(shù)調用跟蹤模塊可獲得該指令屬于哪個關鍵函數(shù),將上面的關鍵字節(jié)歸類為關鍵函數(shù)。這樣隨著程序的運行,即可收集到每個關鍵函數(shù)的關鍵字節(jié)。本文主要對棧溢出、堆溢出、格式化字符串進行漏洞檢測,具體檢查點設置方法如下:
對二進制可執(zhí)行程序進行插樁,讀入Crash 后運行至程序崩潰,收集崩潰點上下文信息。對棧溢出類型的漏洞進行檢查點設置通過檢測在LOAD/STORE指令中對原先棧幀的訪問過程,和當前棧幀進行對比,如果當前棧幀指針高于原棧幀位置,則EIP 可以由用戶控制,該Crash是棧溢出類型的。堆溢出漏洞成因是一塊堆內存被釋放了之后又被使用,又被使用指的是:指針存在(懸垂指針被引用),這個引用的結果是不可預測的,因為不知道會發(fā)生什么。對于該種類型漏洞在污點檢查點選擇捕獲malloc和free函數(shù)的所有調用,當malloc發(fā)生時在列表中保存這些信息,比如基地址、內存大小和分配狀態(tài)(是占用還是空閑),當執(zhí)行LOAD或STORE指令時,檢查該地址是否在列表中,而后檢查其標志,如果該標志是free且在LOAD或STORE中有權限訪問,那就認為是堆溢出漏洞。格式化字符串漏洞兩大危害是內存泄漏和內存寫數(shù)據(jù),主要借助于%s、%c、%d、%p、%x、%n等格式符,格式化字符串的檢查點比較簡單,主要是針對printf函數(shù)族進行污點檢查,驗證是否符合函數(shù)規(guī)范,且現(xiàn)在的編譯器都增加了對格式化符檢測機制,因此該漏洞的實驗驗證階段主要通過CTF 試題和收集的一些存在格式化字符串漏洞的小程序對原型系統(tǒng)進行測試。
本文主要基于Pin插樁平臺開發(fā)出對二進制可執(zhí)行程序進行漏洞檢測,并對二進制可執(zhí)行程序Fuzz 出的Crash 進行分類的工具。實驗對象是存在棧溢出、格式化字符串、堆溢出等緩沖區(qū)溢出漏洞的二進制可執(zhí)行程序,Crash 是由對應的二進制可執(zhí)行程序進行模糊測試得到或從一些測試集中獲取,實驗環(huán)境如表2所示。
表2 實驗環(huán)境
綜合以上幾節(jié),提出Crash 分類框架如圖6 所示。二進制可執(zhí)行程序通過Pin進行插樁,讀入Crash文件,在污點標記階段對Crash 進行污點標注,污點信息分別標注于內存區(qū)域、寄存器指令、關鍵函數(shù)等,在污點傳播階段進行依據(jù)設定策略進行污點跟蹤,主要涉及到重復污點傳播合并和無關污點指令刪除,在污點檢查點收集崩潰點上下文信息,根據(jù)不同類型設置污點檢查點。
圖6 系統(tǒng)執(zhí)行架構圖
類型判定階段主要采用模式匹配方法,通過分析對污點信息收集模塊獲取的LOAD/STORE 指令,寄存器狀態(tài)、內存地址特征,匹配棧溢出、格式化串、堆溢出漏洞崩潰特征。
輸出如下:輸出崩潰點上下文的污點傳播情況、崩潰點指令操作和對應的寄存器內容、棧溢出崩潰點地址、Crash所屬漏洞類型等。
4195584:mov dword ptr[rbp-0x8],0x90909090(rsp:7ffc53538080)(rbp:7ffc53538080)
4195591:mov dword ptr [rbp-0xc],0x91919191(rsp:7ffc53538080)(rbp:7ffc53538080)
[Write Mem B] 400507:mov dword ptr [rbp-0xc],0x91919191
counterWrite:1
4195598:mov dword ptr [rbp-0x4],0x0(rsp:7ffc53538080)(rbp:7ffc53538080)
[Write Mem B] 400523:mov byte ptr [rax],0x45
counterWrite:1
[Write Mem B] 400523:mov byte ptr [rax],0x45
counterWrite:2
[Write Mem B] 400523:mov byte ptr [rax],0x45
counterWrite:3
[Write Mem B] 400523:mov byte ptr [rax],0x45
counterWrite:4
[Write Mem B] 400523:mov byte ptr [rax],0x45
400523:mov byte ptr [rax],0x45 -- Stack overflow in 7ffc53538078
counterWrite:0
如圖7所示,結合IDA進行具體分析驗證該工具的有效性,打開IDA,將位置定位到0x400523,F(xiàn)5 翻譯成偽代碼進行分析,_int64 foo()函數(shù)兩個變量v1、v2 在*((_BYTE *)&v1+(signed int)i)=69存在棧溢出漏洞。
圖7 IDA驗證棧溢出函數(shù)
為了證明該原型系統(tǒng)在Crash類型驗證方面的實用性,實驗驗證階段選取10個CTF二進制可執(zhí)行程序和5個二進制CVE漏洞進行測試,如表3所示。CTF二進制程序對應的Crash由AFL進行fuzzing得出,CTF賽題有棧溢出、堆溢出及格式化字符串3 種且較為簡單,對這些Crash 逐個進行手動調試并結合BitBlaze 工具確認Crash 所屬漏洞類型,留待與原型系統(tǒng)測試結果進行比對。二進制CVE 漏洞程序中,有存在格式化字符串漏洞的Wu-ftpd 2.6.0、Sudo.10,棧溢出漏洞的Libtiff 3.9.2和SWS 0.1.7,堆溢出漏洞的Libproxy 0.3.1,這些漏洞及對應的Crash 由NVD 漏洞庫[22]、吾愛漏洞[23]等網(wǎng)站獲取,Crash類型已經(jīng)標注。
表3 實驗驗證分析歸納
以CVE-2000-0537 為例,該漏洞是在wu-ftpd 2.6.0及其更早版本中存在的漏洞,是一個典型的格式化字符漏洞,可將用戶輸入的數(shù)據(jù)作為格式化字符串傳送給vsprintf()函數(shù)。通過原型系統(tǒng)驗證,可以確定漏洞觸發(fā)地址、棧幀布局、寄存器信息以及Crash 所屬類型等信息。實驗結果表明原型系統(tǒng)可以有效甄別Crash所屬漏洞類型。原型系統(tǒng)準確識別出的Crash所屬類型數(shù)目占Crash樣本標注所屬類型數(shù)的比例近似于71%。
由于Crash 數(shù)量大,與漏洞有直接或間接關系的Crash比例很小,對于由系統(tǒng)無效訪問,空指針訪問等與漏洞無關的無利用價值Crash,這里不進行考慮。通過對以上程序進行Crash 類性判定,與原Crash 樣本中標注的Crash 所屬漏洞類性進行對比,可以計算原型系統(tǒng)判定的準確率。該原型系統(tǒng)的誤報主要是因為漏洞觸發(fā)規(guī)則模塊編寫不夠完善,雖然同種漏洞的原理是一樣的,但是觸發(fā)形式多種多樣,如何合理編寫觸發(fā)特征以減少誤報,是下一步實驗的重點研究之一。
Crash 分析是漏洞挖掘利用的關鍵環(huán)節(jié),本文主要研究Linux 系統(tǒng)下針對二進制可執(zhí)行程序Fuzz 出的Crash 進行分類的問題,提出一種基于污點分析的分類方法,在Pin 插樁平臺上設計了對二進制可執(zhí)行程序進行漏洞檢測和Crash 分類的工具。實驗證明,該工具能夠有效地識別出二進制可執(zhí)行程序存在的漏洞類型,并判斷出Crash和其中的某種漏洞相關。但該工具存在三個主要問題:一是無法有效對存在復合漏洞的二進制可執(zhí)行程序進行分析;二是檢測漏洞的類型不夠完善,由于漏洞觸發(fā)規(guī)則模塊編寫不夠全面,對堆的一些其他漏洞(Fastbin、協(xié)議、邏輯漏洞等)無法進行檢測;三是污點傳播過程中對指令類型的傳播規(guī)則設定不夠全面,由于指令集異常龐大,沒有考慮到一些特殊指令,例如xchg、cdq、rtdsc 等,這在一定程度上增加了誤報率。下一步,將針對以上問題對該工具進行改進,在污點傳播階段增加指令覆蓋面,重點研究如何完善漏洞觸發(fā)規(guī)則,提高匹配效率。