angr源碼分析——Simulation Engines

爲什麼研究這個類呢?原因是在對程序進行符號執行時,step()調用的實際上就是project.factory.successors()函數,而這個函數代碼爲
    def successors(self, *args, **kwargs):
        """
        Perform execution using any applicable engine. Enumerate the current engines and use the
        first one that works. Return a SimSuccessors object classifying the results of the run.
        :param state:           The state to analyze
        :param addr:            optional, an address to execute at instead of the state's ip
        :param jumpkind:        optional, the jumpkind of the previous exit
        :param inline:          This is an inline execution. Do not bother copying the state.
        Additional keyword arguments will be passed directly into each engine's process method.
        """
        return self.project.engines.successors(*args, **kwargs)

所以實際上,最終調用的是engines中的successors()函數對狀態進行操作。因此,通過深入研究engines可以瞭解angr是如何操作states對程序進行模擬執行的。

(這裏有個問題,現在還沒想明白:爲什麼調用的是engines.successors,在successors的初始化函數中,並沒有調用engines.process方法,但是參數最終都會傳給process方法,那麼從哪裏調用的process呢???)

下面是SimEngine的一些方法。

process(state, *args, **kwargs)

執行一個狀態。
我們只在子類裏面重寫此方法以提供正確的方法簽名和文檔。我們應該重寫_prcess方法來進行實際的執行操作。
參數:
state -將要執行的狀態。這個在修改前被複制。
inline -這是一個內聯執行。不影響複製狀態。
force_addr -強制執行,假裝我們正在這個具體地址運行。
返回值:一個SimSuccessors對象對執行的successor狀態進行分類。

check(state, *args, **kwargs)

檢查此引擎是否可用於在當前狀態下執行。回調check_failure在失敗的檢查時被調用。請注意,即使check()返回True,執行仍可能失敗。您只應在子類中重寫此方法以提供正確的方法簽名和文檔字符串。您應該重寫_check方法來執行您的實際執行。
參數:
state(SimState) - 要執行的狀態。
args - 將傳遞給process()的位置參數。
kwargs - 將傳遞給process()的關鍵字參數。
返回:如果狀態可以由當前引擎處理,則爲真,否則爲False。

從代碼中可以看出,SimEngine是一個父類(基類),那麼真正的引擎有一下幾種,它們都重寫了SimEngine類的check方法和process方法。

vex_preset.add_default_plugin('unicorn', SimEngineUnicorn)
vex_preset.add_default_plugin('failure', SimEngineFailure)
vex_preset.add_default_plugin('syscall', SimEngineSyscall)
vex_preset.add_default_plugin('hook', SimEngineHook)
vex_preset.add_default_plugin('  ', SimEngineVEX)

vex_preset.add_default_plugin('procedure_engine', SimEngineProcedure)

下面先主要介紹SimEngineVEX和SimSimEngineUnicorn。

1. SimEngineVEX

基於VEX,Valgrind的IR的執行引擎。

process(state, irsb=None, skip_stmts=0, last_stmt=99999999, whitelist=None, inline=False, force_addr=None, insn_bytes=None, size=None, num_inst=None, traceflags=0, thumb=False, opt_level=None, **kwargs)

參數:
state - 執行的狀態
irsb - 用於執行的PyVEX IRSB對象。如果沒有提供,將被解除。
skip_stmts - 處理中跳過的語句數
last_stmt - 在此語句後不要執行任何語句
whitelist - 僅在此組中執行語句
inline - 這是一個內聯執行。不打擾複製狀態。
force_addr - 強制執行,假裝我們正在這個具體地址工作
thumb - 是否應該在ARM的THUMB模式下解除塊。
opt_level - 要使用的VEX優化級別。
insn_bytes - 用於塊而不是project的字節串。
size - 塊的最大大小,以字節爲單位。
num_inst - 指令的最大數量。
traceflags - traceflags傳遞給VEX。 (默認:0)
返回:
SimSuccessors對象對塊的successors進行分類

lift(state=None, clemory=None, insn_bytes=None, arch=None, addr=None, size=None, num_inst=None, traceflags=0, thumb=False, opt_level=None)

lift an IRSB。
有許多可能的有效參數組。您至少必須傳遞一些數據源,一些架構源和一些地址源。
數據源按優先級順序排列:insn_bytes,clemory,state
地址源,按優先級順序排列:地址addr,狀態state
架構源,按照優先順序排列:arch,clemory,state
參數:
state - 用作數據源的狀態。
clemory - 用作數據源的cle.memory.Clemory對象。
addr - 啓動塊的地址。
thumb - 是否應該在ARM的THUMB模式下解除塊。
opt_level - 要使用的VEX優化級別。最終的IR優化級別由(按優先級排序)確定: - 參數opt_level - 如果狀態選項中存在OPTIMIZE_IR,則opt_level設置爲1 - self._default_opt_level
insn_bytes - 用作數據源的字節字符串。
size - 塊的最大大小,以字節爲單位。
num_inst - 指令的最大數量。
traceflags - traceflags傳遞給VEX。(默認:0)

2.SimEngineUnicorn

Unicorn引擎中的具體執行,qemu的一個分支。

process(state, step=None, extra_stop_points=None, inline=False, force_addr=None, **kwargs)

參數:
state - 執行的狀態
step - 我們要執行多少個基本塊
extra_stop_points - 執行應該暫停的地址集合
inline - 這是一個內聯執行。 不要打擾複製狀態。
force_addr - 強制執行,假裝我們正在這個具體地址工作
返回:

SimSuccessors對象將運行結果和它是否成功進行分類。

對於每個引擎的具體執行細節先暫時不探討。只需要知道,執行的邏輯是從process開始的即可。要想深入研究則跟蹤這個函數走下去就行。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章