angr學習


0、資料

幾個主要的網站

angr的github:https://github.com/angr

angr的document:https://docs.angr.io/

angr的api:https://angr.io/api-doc/

1、angr安裝

我的實驗環境是Ubuntu14.04,顯示安裝依賴:

sudo apt-get install python-dev libffi-dev build-essential virtualenv

然后新建一個python虛擬環境,進入angr環境

virtualenv angr
source angr/bin/activate

安裝angr

sudo pip install angr

2、angr中的基本概念

Project

Project是angr中的基本概念,通過下面的簡單兩行代碼可以新建一個Project變量

import angr
p = angr.Project('/bin/sh')

project中有一些基本屬性,然后打印他們,包括arch中的很多屬性

print(p.arch)
print(p.arch.bits)
print(p.arch.name)
print(p.arch.bytes)
print(p.arch.memory_endness)
print(hex(p.entry))
print(p.filename)

結果

<Arch AMD64 (LE)>
64
AMD64
8
Iend_LE
0x404e32
/bin/sh

loader

loader是表示可執行文件加載到內存之中的變量,同樣先來看一些基本的屬性,打印他們

print(p.loader)#主程序對象,下面的打印結果顯示程序的名字是dash
print(p.loader.shared_objects)#動態庫對象,結果包含了動態連接器、庫以及主程序
print(p.loader.min_addr)
print(p.loader.max_addr)
print(p.loader.main_object)#主對象
print(p.loader.main_object.execstack)#是否有可執行棧,即是否開啟了nx
print(p.loader.main_object.pic)#是否是地址無關代碼

結果如下:

<Loaded dash, maps [0x400000:0x5008000]>
OrderedDict([('dash', <ELF Object dash, maps [0x400000:0x61fde7]>), (u'libc.so.6', <ELF Object libc-2.19.so, maps [0x1000000:0x13c82bf]>), (u'ld-linux-x86-64.so.2', <ELF Object ld-2.19.so, maps [0x2000000:0x22241c7]>)])
4194304
83918848
<ELF Object dash, maps [0x400000:0x61fde7]>
False
True

factory

可以使用project構造一系列對象

Blocks

angr可以從基本塊的角度來分析程序,block代表基本塊,給project.factory.block()函數傳遞一個地址,則會返回一個block對象

看block中有哪些對象,將p.entry傳遞給block函數

block = p.factory.block(p.entry)
print(block)#基本塊信息
print(block.pp())#打印出匯編指令
print(block.instructions)#打印出指令數目
print(block.instruction_addrs)#打印出每條指令的地址

結果:

<Block for 0x404e32, 41 bytes>
0x404e32:    xor    ebp, ebp
0x404e34:    mov    r9, rdx
0x404e37:    pop    rsi
0x404e38:    mov    rdx, rsp
0x404e3b:    and    rsp, 0xfffffffffffffff0
0x404e3f:    push    rax
0x404e40:    push    rsp
0x404e41:    lea    r8, qword ptr [rip + 0x10c88]
0x404e48:    lea    rcx, qword ptr [rip + 0x10c11]
0x404e4f:    lea    rdi, qword ptr [rip - 0x1f6]
0x404e56:    call    0x404900
None
11
[4214322L, 4214324L, 4214327L, 4214328L, 4214331L, 4214335L, 4214336L, 4214337L, 4214344L, 4214351L, 4214358L]

同時,可以使用block來獲得其他的對象

print(block.capstone)
print(block.vex)

States

在angr中,project代表一個可執行文件的映像,如果要模擬執行程序,則需要angr中的SimState的對象states來表示程序狀態

state = p.factory.entry_state()

看里面的一些屬性

print(state.regs.rip)#rip的值
print(state.regs.rax)#rax的值
print(state.mem[p.entry].int.resolved)#以int的格式打印出p.entry處的值

結果,因為是初始狀態,所以初始的rip指向的是p.entry的值

<BV64 0x404e32>
<BV64 0x1c>
<BV32 0x8949ed31>

上面這些都是不python中int值的含義,BV指的Bitvector,位向量。

這樣來進行位向量和int值的轉換

>>> bv = state.solver.BVV(0x1234, 32)       # create a 32-bit-wide bitvector with value 0x1234
<BV32 0x1234>                               # BVV stands for bitvector value
>>> state.solver.eval(bv)                # convert to python int
0x1234
>>> state.regs.rsi = state.solver.BVV(3, 64)
>>> state.regs.rsi
<BV64 0x3>

然后看mem接口

>>> state.regs.rsi = state.solver.BVV(3, 64)
>>> state.regs.rsi
<BV64 0x3>

>>> state.mem[0x1000].long = 4
>>> state.mem[0x1000].long.resolved
<BV64 0x4>

使用數組[索引]符號指定地址

使用.<type>指定內存應該解釋為<type>(常見值:char、short、int、long、size_t、uint8_t、uint16_t…)

從那里,你可以:

為它存儲一個值,可以是位向量,也可以是python int

使用.resolve獲取作為位向量的值

使用.concrete獲取作為python int的值

>>> state.regs.rdi
<BV64 reg_48_11_64{UNINITIALIZED}>

這仍然是一個64位位向量,但它不包含數值。相反,它有一個名字!這被稱為符號變量,它是符號執行的基礎。

Simulation Managers

模擬管理器,管理了程序在執行過程之中的各種接口,看看新建一個模擬管理器,使用statue

simgr = proj.factory.simulation_manager(state)

往下執行一個基本快

simgr.step()

我們可以看看simgr.active[0]來查看我們當前的statue,simgr.active[0].regs.rip則會打印寄存器的RIP,可以發現它和初始化simgr的statue已經不同了

Analyses

project中定義了許多的analyses

proj.analyses.BackwardSlic
proj.analyses.CongruencyCheck
proj.analyses.reload_analyses
proj.analyses.BinaryOptimizer
proj.analyses.DDG
proj.analyses.StaticHooker
proj.analyses.BinDiff
proj.analyses.DFG
proj.analyses.VariableRecovery
proj.analyses.BoyScout
proj.analyses.Disassembly
proj.analyses.VariableRecoveryFast
proj.analyses.CDG
proj.analyses.GirlScout
proj.analyses.Veritesting
proj.analyses.CFG
proj.analyses.Identifier
proj.analyses.VFG
proj.analyses.CFGEmulated
proj.analyses.LoopFinder
proj.analyses.VSA_DDG
proj.analyses.CFGFast
proj.analyses.Reassembler
 
看下面簡單的CFG的例子來了解analyses的簡單用法
# Originally, when we loaded this binary it also loaded all its dependencies into the same virtual address  space
# This is undesirable for most analysis.
>>> proj = angr.Project('/bin/true', auto_load_libs=False)
>>> cfg = proj.analyses.CFGFast()
<CFGFast Analysis Result at 0x2d85130>

# cfg.graph is a networkx DiGraph full of CFGNode instances
# You should go look up the networkx APIs to learn how to use this!
>>> cfg.graph
<networkx.classes.digraph.DiGraph at 0x2da43a0>
>>> len(cfg.graph.nodes())
951

# To get the CFGNode for a given address, use cfg.get_any_node
>>> entry_node = cfg.get_any_node(proj.entry)
>>> len(list(cfg.graph.successors(entry_node)))
2

 


免責聲明!

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



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