angr學習筆記(三)--路徑爆炸問題的處理


符號執行最大的問題就是路徑爆炸,當一個程序存在循環結構時,即使邏輯十分簡單也可能會產生規模十分巨大的執行路徑,本文記錄三種處理路徑爆炸的方法:

1.避免進入循環結果,手動添加約束條件

循環結果如下

 

該循環結構在程序中比較兩個字符串是否相等,每次循環都會有if語句生成兩個不同的分支,路徑成指數級增長,該函數可以通過手動添加約束條件來避免執行

 solution.found[0].solver.add(string1=='BWYRUBQCMVSBRGFU')

使程序停止在該函數之前,再添加約束條件后求解,得出效果與執行完該函數一致

 

import angr
import sys
import claripy
def Go():
    p=angr.Project("./08con",auto_load_libs=False)
    istate=p.factory.blank_state(addr=0x08048627)
    
    buff_addr=0x0804A050
    
    
    passwd0=claripy.BVS('passwd0',16*8)
    
    istate.memory.store(buff_addr,passwd0)
    
    sm=p.factory.simulation_manager(istate)
    
    solution=sm.explore(find=0x08048678)    //提前停止
    
    print(len(solution.found))
    if solution.found:
    
        string1=solution.found[0].memory.load(buff_addr,16)         //讀出此刻狀態下的字符串值
        solution.found[0].solver.add(string1=='BWYRUBQCMVSBRGFU')   //對此刻字符串值條件約束條件
        solution0=solution.found[0].solver.eval(passwd0,cast_to=bytes)  //求解該字符串


        print("[+] Success! Solution is: {}".format(solution0))
    else:
        raise Exception("error")
        
        
if __name__=="__main__":
    Go()

 

 

2.hooks方法

就是用我們自己設計的函數去取代被hook的函數

找到會導致路徑爆炸的函數,用自己編寫的函數取代該函數即可,可以利用函數地址hook,也可以利用函數名進行hook

 

利用函數地址hook:

@p.hook(check_equals_called_address, length=instruction_to_skip_length)
    def skip_check(state):
        flag=state.memory.load(buff_addr,16)
        string1='XKSPZSJKJYQCQXZV'
        state.regs.eax=claripy.If(
            string1==flag,
            claripy.BVV(1,32),
            claripy.BVV(0,32)
        )

@p.hook() 第一個參數是需要被hook的函數地址,length是call該函數指令占據的字節大小

 

 如圖,addr=0x80486B8,length=D-8

 

 state.regs.eax=claripy.If()
設置寄存器eax的值,使該函數與被hook的函數具有一樣的效果,函數的返回值被保存在eax中,字符串相等則返回BVV(1,32),否則返回BVV(0,32)



利用函數名hook
當一個需要被hook的函數被調用了很多次時,利用地址hook便會出現問題,而通過程序的符號表利用函數名完全可以解析出地址
hook函數名的方法:
class Replace_check(angr.SimProcedure):
		def run(self,user_input,length):
			user_input_addr=user_input
			flag=self.state.memory.load(user_input_addr,length)
			string1='WQNDNKKWAWOLXBAC'
			
			self.state.regs.eax=claripy.If(
				string1==flag,
				claripy.BVV(1,32),
				claripy.BVV(0,32)
				)
	
check_funcname='check_equals_WQNDNKKWAWOLXBAC'
	
p.hook_symbol(check_funcname,Replace_check())

  

class Replace_check(angr.SimProcedure) 需要替換的函數名 Replace_check()
def run(self,user_input,length)  run函數名固定,self后面的參數與被hook的函數參數保持一致
p.hook_symbol(check_funcname,Replace_check())  第一個參數時被替換的函數名,第二個參數是構造出來的函數
完成exp
import angr
import sys
import claripy
def Go():
    p=angr.Project("./10sim",auto_load_libs=False)
    istate=p.factory.entry_state()
    
    class Replace_check(angr.SimProcedure):
        def run(self,user_input,length):
            user_input_addr=user_input
            flag=self.state.memory.load(user_input_addr,length)
            string1='WQNDNKKWAWOLXBAC'
            
            self.state.regs.eax=claripy.If(
                string1==flag,
                claripy.BVV(1,32),
                claripy.BVV(0,32)
                )
    
    check_funcname='check_equals_WQNDNKKWAWOLXBAC'
    
    p.hook_symbol(check_funcname,Replace_check())
    
    sm=p.factory.simulation_manager(istate)
    
    def succ(state):
        output1=state.posix.dumps(1)
        if b'Good Job.' in output1:
            return True
        else:
            return False
            
    def _abort(state):
        output2=state.posix.dumps(1)
        if b'Try again.' in output2:
            return True
        else:
            return False
    
    solution=sm.explore(find=succ,avoid=_abort)
    print(len(solution.found))
    if solution.found:
        solution0=solution.found[0].posix.dumps(0)
        print(solution0)
    else:
        raise Exception("error")
        
        
if __name__=="__main__":
    Go()

 



3.veritesting技術處理路徑爆炸
簡單粗暴,只需要在angr里我們只要在構造模擬管理器時,啟用Veritesting了就行
sm=p.factory.simulation_manager(istate,veritesting=True)

忽視循環結構,直接硬懟,耗時較長

完整版
import angr
import sys
import claripy
def Go():
	p=angr.Project("./12ver",auto_load_libs=False)
	istate=p.factory.entry_state()
	
	sm=p.factory.simulation_manager(istate,veritesting=True)
	
	def succ(state):
		output1=state.posix.dumps(1)
		if b'Good Job.' in output1:
			return True
		else:
			return False
			
	def _abort(state):
		output2=state.posix.dumps(1)
		if b'Try again.' in output2:
			return True
		else:
			return False
	
	solution=sm.explore(find=succ,avoid=_abort)
	print(len(solution.found))
	if solution.found:
		solution0=solution.found[0].posix.dumps(0)
		print(solution0)
	else:
		raise Exception("error")
		
		
if __name__=="__main__":
	Go()

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM