angr初探

狒猩橙發表於2023-02-22

前言

在搞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.posixPOSIX相關的環境介面,例如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列表中,若無法求解則該列表為空。