前言
在搞fuzz
的時候發現了一個比較難以解決的問題。例如if(*buf == "\xde\xad\xbe\xef")
,我們如果想透過純fuzz
去進入這個if
的分支,那麼機率極其微小。這就使我不得不去嘗試透過一些其他的方法去解決這個問題。於是我想到了一個比較出名符號執行的工具————angr
。這篇文章記錄筆者入門angr
的過程。
環境安裝
angr 的安裝
angr
的安裝非常簡便,透過pip
即可,不過貌似angr
因為會依賴很多其他的庫,所以它的創作者推薦把他裝在虛擬環境當中,不過筆者就直接裝在虛擬機器裡了。
pip3 install angr
學習環境安裝
我這裡用的是github
上的一個專案對angr
進行入門學習。
git clone https://github.com/jakespringer/angr_ctf.git
angr 基本使用方法
angr.Project
這是我們分析一個二進位制檔案的第一步,就是建立一個angr.Project
類,我們的後續操作都將基於這個類展開。並且我們可以透過所建立的project
獲取二進位制檔案的一些基本資訊。如:project.arch
可以獲得這個二進位制檔案的架構,project.entry
可以獲得這個二進位制檔案的起始地址,proj.filename
獲得這個二進位制檔案的名字。
例如:
import sys
import angr
bin_path = "./00_angr_find"
project = angr.Project(bin_path)
print(project.arch)
print(hex(project.entry))
print(project.filename)
結果:
<Arch X86 (LE)>
0x80490b0
./00_angr_find
project.factory
project.factory
為我們提供了一些實用的類的構造器
project.factory.block(address)
angr
是以基本塊為單位進行的分析,project.factory.block(address)
可以獲得給定地址所在的基本塊
。.pp()
可以獲得該基本塊的彙編程式碼。
例如:
block = project.factory.block(project.entry)
block.pp()
結果:
_start:
80490b0 endbr32
80490b4 xor ebp, ebp
80490b6 pop esi
80490b7 mov ecx, esp
80490b9 and esp, 0xfffffff0
80490bc push eax
80490bd push esp
80490be push edx
80490bf call 0x80490e7
project.factory.entry_state()
project.factory.entry_state()
用來獲取一個程式的初始執行狀態。
project.factory.blank_state(addr)
project.factory.blank_state(addr=...)
用來獲取一個程式從指定地址開始執行的空白狀態。
state - 模擬執行狀態
無論是project.factory.entry_state()
,還是project.factory.blank_state(addr=...)
,都會返回一個模擬執行狀態,我們可以把它存放到某個變數裡,如存到state
裡。
state.regs
state.regs
可以獲取一些暫存器的值,如state.regs.esp
即可獲得esp
的值。我們可以對其直接進行加減操作。
例如:
init_state = project.factory.entry_state()
print(init_state.regs.esp)
init_state.regs.esp-=12
print(init_state.regs.esp)
結果:
<BV32 0x7ffeffac>
<BV32 0x7ffeffa0>
state.memory
state.memory
是訪問記憶體介面的一種形式。state.memory.load(addr, size_in_bytes)
:獲取該地址上指定大小的位向量。state.memory.store(addr, bitvector)
:將一個位向量儲存到指定地址、
state.posix
state.posix
是POSIX
相關的環境介面,例如state.posix.dumps(fileno)
獲取對應檔案描述符上的流。
simulation_manager - 模擬執行器
angr
將一個狀態的執行方法獨立成一個SimulationManager
類,有以下兩種寫法:
1、simgr = proj.factory.simgr(state)
2、simgr = proj.factory.simulation_manager(state)
simgr.step()
simgr.step()
:以基本塊為單位的單步執行。
simgr.explore(find)
simgr.explore(find)
:路徑探索,即執行到指定地址並進行約束求解,將執行完成的狀態放在simgr.found
列表中,若無法求解則該列表為空。