【扩展angr】自定义exploration_technique

在angr文档里发现writing exploration technique的部分是空的。然后,恰好看到一篇博客讲了如何控制符号执行的资源消耗,看到里头的代码是基于自定义exploration technique来实现的。

如果对于如何控制符号执行的内存消耗感兴趣可以看这篇博客:

https://degrigis.github.io/posts/explosion_detector/

先来看看他的例子,这个代码的思路是利用psutil获取进程占用的内存信息。如果占用的内存超出了设定的最大内存值,则将active的状态移为out_of_memory的状态去。

import angr
class MemLimiter(angr.exploration_techniques.ExplorationTechnique):
    def __init__(self, max_mem, drop_errored):
        super(MemLimiter, self).__init__()
        self.max_mem = max_mem # 设定最大内存
        self.drop_errored = drop_errored
        self.process = psutil.Process(os.getpid())

    def step(self, simgr, stash='active', **kwargs):
        #如果内存占用超过90%或者内存超出了设定的最大值,则将active状态移到out_of_memory状态
        if psutil.virtual_memory().percent > 90 or (self.max_mem - 1) < self.memory_usage_psutil:
            simgr.move(from_stash='active', to_stash='out_of_memory')
            simgr.move(from_stash='deferred', to_stash='out_of_memory')
		# 丢弃deadended,avoid,found状态,暂时没明白为什么要丢弃,是因为超出内存大小,所以不需要这些不是很重要的状态了?
        simgr.drop(stash='deadended')
        simgr.drop(stash='avoid')
        simgr.drop(stash='found')
        if self.drop_errored:
            del simgr.errored[:]

        return simgr.step(stash=stash)
	
    #将内存使用情况设为这个类的属性
    @property
    def memory_usage_psutil(self):
        # return the memory usage in MB
        mem = self.process.memory_info().vms / float(2 ** 30)
        return mem

这个例子给了一个很好的例子,来告诉我们如何写exploration_technique…

首先创建一个类,继承angr里的类:angr.exploration_techniques.ExplorationTechnique,其次,这个类里有两个方法需要自己完善,一个是__init__,另一个是step。

init中可以使用super来直接使用父类的init方法。

step中的参数有以下几个:

  • simgr(模拟执行的管理器)
  • stash=‘active’:stash是保存状态的列表,这里是只处理active状态
  • **kwargs:允许不定长度的键值对来作为参数传递给一个函数。
class className(angr.exploration_techniques.ExplorationTechnique):
	def __init__(self):
        super(className, self).__init__()
    def step(self,simgr,stash='active',**kwargs):
        return simgr.step(stash=stash)

这个例子简单介绍了如何写exploration_technique,但是没说如何使用你定义好的exploration_technique。贴心的作者又贴出了一个检测状态爆炸的代码,这段代码也介绍了如何使用自定义的exploration_technique。

先来看explosion_detector这个类。init方法内,还是一样,需要继承父类的init方法。这里省略了大部分的代码。因为和本次博客主题没啥关系。

class ExplosionDetector(ExplorationTechnique):
    def __init__(self, stashes=('active', 'deferred', 'errored', 'cut'), threshold=100):
        super(ExplosionDetector, self).__init__()
        ...
    def step(self, simgr, stash='active', **kwargs):
        simgr = simgr.step(stash=stash, **kwargs)
        ...
        return simgr

然后是使用自定义的exploration_technique的代码,主要是14行和15行,使用simgr对象里的use_technique方法,参数为刚才写的exploration_technique的类。

from threading import Event, Timer

'''
project: an angr Project object
state: state that will be used to start dse
'''
def dse_it(project, state):

    sm = project.factory.simgr(state)

    dfs = angr.exploration_techniques.DFS()
    sm.use_technique(dfs)
    ed = ExplosionDetector(threshold=1000)
    sm.use_technique(ed)

    # Callback for timeout that sets the boolean inside the 
    # ExplosionDetector
    def timeout():
        l.warning("Timeout during DSE has been reached.")
        ed.timed_out.set()
        ed.timed_out_bool = True

    # The actual timer
    timer = Timer(300, timeout)
    timer.start()

    while len(sm.active) > 0 and not ed.timed_out_bool:
        new_state = sm.active[0]
        state_addr = new_state.solver.eval(new_state.regs.pc)
        sm.step()

    # Cancel the timer
    timer.cancel()
    
    # Check ExplosionDetector and do something if we timed out.
    if ed.timed_out_bool:
        l.fatal("DSE timed out")

总结一下,构造exploration_technique的模板为

class className(angr.exploration_techniques.ExplorationTechnique):
	def __init__(self):
        super(className, self).__init__()
    def step(self,simgr,stash='active',**kwargs):
        return simgr.step(stash=stash)

使用exploration_technique的代码为:

cn = className() # className为你定义的exploration_technique那个类的名字
simgr.use_technique(cn) #  simgr为simulation_manager,相信看到这个博客的都知道是啥东西吧

参考资料:

  • https://degrigis.github.io/posts/explosion_detector/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破落之实

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值