angr使用学习(持续更新)

首先我是直接在kali中安装的,也是边练边学的。

嗯,要在纯净python环境,所以是在 virtualenv 虚拟环境里,也不是特别会用这个,按照教程一步步做的

source venv/bin/activate

进入了对应环境

退出是

deactivate

 en,ipython交互性确实好一些

00_angr

import angr
p=angr.Project('./dist/00_angr_find')
init_state=p.factory.entry_state()
sm=p.factory.simulation_manager(init_state)
sm.explore(find=0x8048678)
# sm.found[0]
found_state=sm.found[0]
found_state.posix.dumps(0)

得到正确字符串 

01_angr

嗯,最好都加一个 avoid=  ,也可以加快模拟

02_angr

sm.explore( )参数也可以是字符串。

不知道为什么写地址跑不出来。

import angr
p=angr.Project('./dist/02_angr_find_condition')
init_state=p.factory.entry_state()
sm=p.factory.simulation_manager(init_state)
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b'Try again' in state.posix.dumps(1)
sm.explore(find=is_good,avoid=is_bad)
if sm.found:
    found_state=sm.found[0]
    print(found_state.posix.dumps(0))
    

使用指定地址作为目标(find=address)没有预期的效果,但使用字符串匹配时却可以正常工作。这可能是由于以下几种原因:

  1. 路径爆炸angr在分析复杂的二进制程序时可能会遇到路径爆炸问题,即存在大量的执行路径。设置特定地址作为目标可能无法让angr找到正确的路径,因为它可能在其他路径上花费太多时间或资源。

  2. 目标地址不可达:目标地址可能并不是代码执行的直接目标。例如,如果目标地址在特定条件下才能被执行,而条件不满足,angr就无法到达该地址。

  3. 代码优化或跳转:编译器的优化可能导致目标地址的直接访问变得复杂,例如内联函数或跳转指令。字符串匹配可能会更直接地找到这些代码片段。

  4. 符号执行约束angr依赖于符号执行来探索程序的执行路径。如果约束条件太复杂或过于松散,可能无法正确解析所有可能的执行路径。

03_angr

是有三个输入,angr好像不支持多个输入

定义为符号变量(BVS)并表示为比特向量(bit vectors)

嗯,就是起始位置可以自定义,变量可以自己通过寄存器设置

存储在寄存器中了

entry_state()

entry_state() 创建一个状态,表示程序刚刚开始执行时的状态。它使用指定的二进制文件,按照正常程序启动时的方式初始化状态。这通常包括设置程序的入口点、初始化栈指针、程序计数器等。

blank_state()

blank_state() 创建一个最小化的空状态,没有对特定二进制文件进行初始化。它只设置基本的架构信息和一些默认状态,允许用户完全自定义状态。

特点:
  1. 无特定入口点:程序计数器(PC)不会被设置为二进制文件的入口点。
  2. 手动初始化:所有寄存器、内存和环境都需要手动初始化。
  3. 灵活性:提供了更高的灵活性,允许用户设置特定的初始条件和状态。

但是 entry_state() 也可以设置开始地址,不过后面都是 blank_state() 用的多 

import angr
import claripy
p=angr.Project('./dist/03_angr_symbolic_registers')
state_addr=0x08048980
init_state=p.factory.blank_state(addr=state_addr)
pass1=claripy.BVS('pass1',32)
pass2=claripy.BVS('pass2',32)
pass3=claripy.BVS('pass3',32)
init_state.regs.eax=pass1
init_state.regs.ebx=pass2
init_state.regs.edx=pass3

sm=p.factory.simulation_manager(init_state)
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b'Try again' in state.posix.dumps(1)

sm.explore(find=is_good,avoid=is_bad)
if sm.found:
    found_state=sm.found[0]
    password1=found_state.solver.eval(pass1)
    password2=found_state.solver.eval(pass2)
    password3=found_state.solver.eval(pass3)
    # input hex(not dos)
    print("Solution: {:x} {:x} {:x}".format(password1,password2,password3))
else:
    raise Exception("No Solution")

是要十六进制的输入

04_angr

变量在堆栈中,需要先模拟堆栈

那个ebp是父ebp,保存完父函数ebp才开辟本函数栈空间,当函数执行完以后会有一个pop ebp恢复父函数ebp,但是因为我们要执行的代码与父函数无关,只用执行到find的地方就可以了,不用返回父函数接着执行,所以保存不保存父函数ebp都无所谓

import angr
p=angr.Project('./dist/04_angr_symbolic_stack')
state_addr=0x08048697
init_state=p.factory.blank_state(addr=state_addr)

# 布局堆栈
padding_size=8
init_state.stack_push(init_state.regs.ebp)
init_state.regs.ebp=init_state.regs.esp
init_state.regs.esp-=padding_size

# 变量
pass1=init_state.solver.BVS('pass1',32)
pass2=init_state.solver.BVS('pass2',32)
init_state.stack_push(pass1)
init_state.stack_push(pass2)

sm=p.factory.simgr(init_state)
#==sm=p.factory.simulation_manager(init_sate)
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b'Try again' in state.posix.dumps(1)

sm.explore(find=is_good,avoid=is_bad)

if sm.found:
    found_state=sm.found[0]
    password1=found_state.solver.eval(pass1)
    password2=found_state.solver.eval(pass2)
    print("Solution: {} {}".format(password1,password2))
else:
    raise Exception("Solution not find")

05_angr

变量写在内存中

scanf('%8s',unk_404233)  大小 8 个字节

import angr
p=angr.Project('./dist/05_angr_symbolic_memory')
state_addr=0x08048601
init_state=p.factory.blank_state(addr=state_addr)
p1=init_state.solver.BVS('p1',64)
p2=init_state.solver.BVS('p2',64)
p3=init_state.solver.BVS('p3',64)
p4=init_state.solver.BVS('p4',64)
p1_addr=0x0A1BA1C0
p2_addr=0x0A1BA1C8
p3_addr=0x0A1BA1D0
p4_addr=0x0A1BA1D8
init_state.memory.store(p1_addr,p1)
init_state.memory.store(p2_addr,p2)
init_state.memory.store(p3_addr,p3)
init_state.memory.store(p4_addr,p4)

sm=p.factory.simgr(init_state)
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b'Try again' in state.posix.dumps(1)
sm.explore(find=is_good,avoid=is_bad)

if sm.found:
    found_state=sm.found[0]
    pass1=found_state.solver.eval(p1,cast_to=bytes)
    pass2=found_state.solver.eval(p2,cast_to=bytes)
    pass3=found_state.solver.eval(p3,cast_to=bytes)
    pass4 = found_state.solver.eval(p4, cast_to=bytes)
    print("Solution: {} {} {} {}".format(pass1.decode('utf-8'),pass2.decode('utf-8'),pass3.decode('utf-8'),pass4.decode('utf-8')))
    print("Solution: {} {} {} {}".format(pass1,pass2,pass3,pass4))
else:
    raise Exception('no solution')
#Solution: NAXTHGNR JVSFTPWE LMGAUHWC XMDCPALU
#Solution: b'NAXTHGNR' b'JVSFTPWE' b'LMGAUHWC' b'XMDCPALU'

符号变量 p1 等被定义为 64 位比特向量。cast_to=bytes 可以将这些比特向量转化为对应的字节表示。否则,默认情况下,eval 可能返回一个整数表示。 

06_angr

动调分配内存-->指定一块内存给他用

import angr
p=angr.Project('./dist/06_angr_symbolic_dynamic_memory')
state_addr=0x08048699
init_state=p.factory.blank_state(addr=state_addr)
# open space
print('ESP:',init_state.regs.esp)
# 0x7fff0000 not started
buffer0=0x7fff0000-100
buffer1=0x7fff0000-200
# buffer==pointer
buffer0_addr=0x0ABCC8A4
buffer1_addr=0x0ABCC8AC
init_state.memory.store(buffer0_addr,buffer0,endness=p.arch.memory_endness)
init_state.memory.store(buffer1_addr,buffer1,endness=p.arch.memory_endness)
p1=init_state.solver.BVS('p1',64)
p2=init_state.solver.BVS('p2',64)
init_state.memory.store(buffer0,p1)
init_state.memory.store(buffer1,p2)

sm=p.factory.simgr(init_state)
def is_good(state):
   return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
   return b'Try again' in state.posix.dumps(1)
sm.explore(find=is_good,avoid=is_bad)
if sm.found:
   found_state=sm.found[0]
   pass1=found_state.solver.eval(p1,cast_to=bytes)
   pass2=found_state.solver.eval(p2,cast_to=bytes)
   print("Solution: {} {} ".format(pass1.decode('utf-8'),pass2.decode('utf-8')))
else:
   raise Exception('no solution')

那个endness 好像是端序问题

07_angr

有一个对文件读取的操作,ignore应该是要avoid的,但不是好像

首先,文件名也可符号化

import angr
p=angr.Project('./dist/07_angr_symbolic_file')
state_addr=0x080488D6
init_state=p.factory.blank_state(addr=state_addr)

# 插入符号化文件
filename="OJKSQYDP.txt" #文件名也可符号化
file_size=0x40
password=init_state.solver.BVS('password',file_size*8)
sim_file=angr.storage.SimFile(filename,content=password,size=file_size)
init_state.fs.insert(filename,sim_file)

sm=p.factory.simgr(init_state)
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b"Try again" in state.posix.dumps(1)

sm.explore(find=is_good,avoid=is_bad)
if sm.found:
    found_state=sm.found[0]
    password_bytes=found_state.solver.eval(password,cast_to=bytes)
    print("Solution {}".format(password_bytes))
else:
    raise Exception('no solution')

好像有的也可以直接指定 cast_to=str  ,这个不行,decode也会报错

官方给的题解,还有一个 file_options='r' 在SimFile 处 ,但我加上还报错了

08_angr

这个题目是去解决路径爆炸的问题

程序的条件分支(如if语句)会产生多条执行路径,随着执行的深入,路径数量呈指数级增长,导致符号执行引擎需要跟踪的路径数目过多,资源消耗巨大

这个逐个字节比对也是会造成路径爆炸

import angr
p=angr.Project('./dist/08_angr_constraints')
state_addr=0x08048625
init_state=p.factory.blank_state(addr=state_addr)

buffer_addr=0x0804A050
password=init_state.solver.BVS('password',16*8)
init_state.memory.store(buffer_addr,password)
sm=p.factory.simgr(init_state)

check_addr=0x08048673
sm.explore(find=check_addr)
if sm.found:
   check_state=sm.found[0]
   desired_str="AUPDNNPROEZRJWKB"
   # param
   check_param1=buffer_addr
   check_param2=16
   check_bvs=check_state.memory.load(check_param1,check_param2)
   check_constraints=desired_str==check_bvs
   check_state.add_constraints(check_constraints)
   passstr=check_state.solver.eval(password,cast_to=bytes)
   print("Solution: {}".format(passstr))
else:
   raise Exception('no find')

09_angr

这题用到了 hook ,也是要好好学习一下。

其实这题和上面那个差不多

本来应该输入两个 16 字节字符串 ,直接输入 32 字节,多的好像是在缓冲区里,下面的就直接用了。

函数返回值一般存储在 eax 里(int ,bool)

import angr
import claripy #符号求解引擎
p=angr.Project('./dist/09_angr_hooks')
init_state=p.factory.entry_state()

# hook
check_addr=0x080486B3
check_skip_size=5
@p.hook(check_addr,length=check_skip_size)
def check_hook(state):
    user_input_addr=0x0804A054
    user_input_length=16
    # read
    user_input_bvs=state.memory.load(user_input_addr,user_input_length)
    desired_str="XYMKBKUHNIQYNQXE"
    state.regs.eax=claripy.If(
        desired_str==user_input_bvs,
        claripy.BVV(1,32),
        claripy.BVV(0,32)
    )
    
def is_good(state):
    return b'Good Job' in state.posix.dumps(1)
def is_bad(state):
    return b'Try again' in state.posix.dumps(1)
sm=p.factory.simgr(init_state)
sm.explore(find=is_good,avoid=is_bad)

if sm.found:
   found_state=sm.found[0]
   print("Solution:{}".format(found_state.posix.dumps(0)))
else:
   raise Exception('no solve')

其实也是不太理解

改为 user_input_length=32 ,就 no solve

10_angr

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值