ubuntu16下 和windows10下 的angr安裝及學習


ubuntu16

首先是需要python3.6以上的版本 用以下方法更新 (摘抄於https://zhuanlan.zhihu.com/p/51340766

1.安裝編譯環境

sudo apt-get install zlib1g-dev libbz2-dev libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libpcap-dev xz-utils libexpat1-dev liblzma-dev libffi-dev libc6-dev

2.下載Python-3.6.3.tar.xz   國內鏡像

3.解壓

tar xvJf Python-3.7.1.tar.xz

4.配置安裝位置

./configure --prefix=/usr/bin/python3.7

5.編譯及安裝

sudo make && sudo make install

 弄完之后直接

pip3 install angr

 

今天打比賽 空余時間搗鼓 弄了一整天都有成功把去平坦化弄好嗚嗚嗚 再見angr

windows10

直接使用python2.7即可

依次執行以下命令(首先需要安裝pip

pip install --upgrade pip
pip install GitPython pip install pyvex pip install unicorn pip install simuvex pip install angr

import angr之后會有warning  說明安裝成功

 

學習

這里使用了Null戰隊編寫的《從0到1》內容

自己總結到一般來說angr跑題到步驟

1.創建一個project對象 

p = Project('r100',auto_load_libs = False)

 這里后面追加的 auto_load_libs 是否自動載入依賴庫 一般設置為False 以減少angr的工作量

2.設置一個啟動狀態state

p.factory.blank_state(addr=xxx)
#可自定義入口地址  一般我解題使用這個
p.factory.entry_state()
#從程序入口點開始 默認會使用這個
p.factory.full_init_state()
#和entry_一樣 不過這之前會調用每個庫的初始化函數 會給angr增加工作量

3.創建虛擬執行

sm = p.factory.simulation_manager(state)
#其中的state就是步驟2里面設置的啟動狀態

4.執行! 去往想去的地方  規避不想去的地方

sm.explore(find = 0x400844,avoid = 0x400855)
#find 和 avoid 可以傳數組進來的 如果有多個想去的或者規避的

5.輸出結果

if sm.found[0]:
    print (sm.found[0].posix.dumps(0).replace(b'\x00',b''))
#成功的結果放在sm.found里面 這是個數組 一般我們想要的結果都是唯一解 然后用posix.dumps(0)輸出 這里的0是標准輸入的意思 replace讓結果清晰

這是最簡單的一個操作 接下來補充一些花里胡哨的操作

  • 一些函數對結果沒有影響,比如printf 我們可以直接讓它返回,代碼如下
p.hook_symbol('printf',SIM_PROCEDURES['stubs']['ReturnUnconstrained'](),replace = True)
#這里吧需要處理對函數名替換printf就可以了
  • 既然可以hook我們認為對結果無影響對函數,那么也可以自己寫一個函數去hook原本對函數,從而達到給angr減少工作量對目的
class my_fgets(SimProcedure): # 固有格式
    def run(self,s): # 參數為 (self + 該函數實際參數)
        simfd = self.state.posix.get_fd(0) # 創建一個標准輸入對對象
        data,real_size = simfd.read_data(12) # 注意該函數返回兩個值 第一個是讀到的數據內容 第二個數內容長度
        self.state.memory.store(s,data) # 將數據保存到相應參數內
        return 12 # 返回原本函數該返回的東西
p.hook_symbol('fgets',my_fgets(),replace = True)

如果是寫scanf的%d如下

class my_sacnf(SimProcedure): # 固有格式
    def run(self,fmt,n): # 參數為 (self + 該函數實際參數)
        simfd = self.state.posix.get_fd(0) # 創建一個標准輸入對對象
        data,real_size = simfd.read_data(4) # 注意該函數返回兩個值 第一個是讀到的數據內容 第二個數內容長度
        self.state.memory.store(n,data) # 將數據保存到相應參數內
        return 1 # 返回原本函數該返回的東西
p.hook_symbol('__isoc99_scanf',my_scanf(),replace = True)
# 這里%d對應int 是4個字節 但是讀取到一個int所以返回1  所以這完全是模擬的原來的函數
  • 一個優化開關,無法避免無解的情況產生,但是能大大提高腳本的運行效率
sm.one_active.options.add(options.LAZY_SOLVES)
  • 自己構造輸入

因為使用標准輸入經常無法推測輸入字符串的長度,會浪費大量時間去嘗試不同長度,所以我們可以自定義輸入 然后作為參數傳入一個函數,這個時候state要設置為call的地址

flag_chars = [BVS('flag_%d'%i,32) for i in range(13)] 
# BVS類似於z3中的BitVec,第一個參數為變量名,第二個參數為位數(bit) 這里我們知道輸入了13個int 所以申請13個約束變量
for i in range(13):
    state.mem[state.regs.rsp + i * 4].dword = flag_chars[i]
#這里為了方便 先把內容儲存在rsp指向的內存 注意一個int是4字節
state.regs.rdi = state.regs.rsp # 然后傳參給rdi

因為是手動設置的輸入,不能通過dump(0) dump標准輸入來得到輸入,這里使用angr求解器提供的eval函數

flag = ''.join(chr(sm.one_found.solver.eval(c)) for c in flag_chars)
# sm.one_found.solver.eval(flag_char[i]) 得到一個int 然后轉為char即可
  •  對於開啟了PIE的可執行文件,angr會默認其基地址為0x400000,此時所有操作只需要在原本地址上加上offset即可
  • 對內存對儲存魚讀取
state.memory.store(addr,data)
# 這里對data可以是一串數據 data🉑️來源於simfd.read_data(標准輸入)
text = sm.one_found.solver.eval(sm.one_found.memory.load(addr,len),cast_to = bytes)
# sm.one_found.memory.load 加載內存     cast_to = bytes  轉為char

 


免責聲明!

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



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