angr 源码分析,exploration Technology中从successors函数到step的state分配过程分析

angr doc(http://angr.io/api-doc/angr.html#module-angr.calling_conventions)中有一段写到关于我们自定义Exploration Techniques的方法,其实Exploration Techniques的方法中有很多我们可以自己实现,并且控制我们的angr控制流程的,但是在angr Documentation中(https://docs.angr.io/extending-angr/todo-writing-exploration-techniques),这一部分放在了todo list里面,所以至今没有一个官方的操纵Exploration Techniques的例子存在,第一步如果我们要分析exploration Technology中的successors函数到step的state分配过程,就要先了解exploration Technology中每个函数的作用是什么。

这个是官方的描述文件的截图,不用很仔细的看,我画一个图片大家可能就理解了。

这个是我追踪每个函数得到的exploration的执行流程,今天我们主要分析的是从step_state  中会有一个一个函数successor获得当前state的后面的succ 的过程,并且会将这些succs进行分类,这些succs的种类就是(https://docs.angr.io/core-concepts/simulation)这个网址中的分类,之后进行一系列的分析,就变成(https://docs.angr.io/core-concepts/pathgroups)这个网址里面的一部分stash types中的一个类别下面的一个。分类完之后如果stash[active]中还有state,从而进行下一轮的step操作,如果没有就会进入complete操作,说明当前的exploration结束,没有可以进一步探索的state了。

分析succesor函数

这是我自己定义的successors的函数的其中第一行代码,就是获得当前状态之后的successors,其实也是在这个函数中,angr处理我们当前state block中的代码,将每一行capstone反汇编之后的代码变为用vex表示的代码块,之后每一行vex语句进行分析,不同的种类的语句使用不同的handler进行不同的处理,之后的博客中我应该会将我的分析写下来吧。这样我们就得到了我们succ这样的一个对象,我将这个对象的内部结构截一个图

可以看到其中主要的内部结构和(https://docs.angr.io/core-concepts/simulation)这个网址中介绍的大部分相同,all_successors = flat_successors + successors + unsat_successors, unsat_successors可能是约束不成功,也有可能是具体值比较没有成功。successors是约束成功,flat_successors是间接跳转到符号值时,如果符号值的约束小于256就会到将所有的可能性的state展开,之后放入flat_successors,如果间接跳转是符号值,并且可能性大于256的时候就会放入unconstrainted_successors这个list里面。

同时successors的返回值,是我们操作过之后的succ,也就是simgr.successors的返回值,我的simgr其实就是simulation.manager的简称,

这个就是我的返回值,当我们返回了这个succ之后,真正的分类操作就开始了。

state分类

从我的return succ开始debug我们的程序流程,return succ之后,程序会跳转到hookset.py下面的一个__call__函数中,

这是angr中hook相关函数后必走的一段路程,由于我们重写了exploration Technology中的一些函数,所以自然会跳转到这个文件中,angr中的hook类似于一张表,当调用这个表中的函数时会跳转到相应的hook的函数中去运行,之后返回我们的sim_manager.py中的step_state函数,在sim_manager.py中的step_state中调用了self.successors这个函数,由于这个函数我们hook了,所以会通过hookset.py中的__call__函数跳转到我们自定义的successor函数中,又由于在自己编写的step_state中调用了sim_manager的step_state函数,所以返回之后会到原先angr自带的step_state函数中。

之后会新建一个dict,名字为stashes,并且将我们的所有state通过不同的名称存储起来,由于我们没有报错,就返回这个stashes了。

返回到我自定义的step_state中的调用sim_manager的中的step_state函数语句这里,并且返回,其实就是返回了一个创建的stashes

之后来到了sim_manager.py中的step函数,

这一条语句在step这个函数的一个for循环中,先放一下这个for循环的整体代码

第一行,for state in self._fetch_states(stash=stash),其实这个fetch_states是一个函数,stash=stash后面的stash是一个str的关键字,我们跟踪就会发现其实就是返回我们当前stashes里面的active那个list里面的state,也就是说我们这个for循环的本质就是遍历当前stashes中的active这个list中的所有state,先来一张fetch_state函数的截图

其实一般运行前两行就结束了,追踪就会发现,其实stash就是一个等于‘active’的str。

重新回到那个for循环,for循环里面的第三段代码都是关于state的筛选问题的,其中用到了两个我们exploration Technology中可以重写的函数,一个就是filter,另外一个就是selector这个两个函数,具体哪个函数忘记了,我们在explore这个函数中定义的avoid=这个条件,就是在其中一个函数中做判断,如果条件成立,这个state就不会执行setp_state这个函数,而是append到相应的bucket中,只有经过filter和selector这两个函数的检验和筛选,才会到下一步的step_state中执行。

之后就是pre_errored = len(self._errored) 这个应该是记录相应的error的,其实在sim_manager中也又error表示当前所有过程中遇到的error问题。下一就就是获得了我们step_state的具体值,就是我们上面返回的stash。

这个if可以分开来看,后面就是我们定义了pre_errored这个error的长度,处理完这个step_state之后再判断len(self._errored)是不是相等,意思就是判断一下在处理这个state过程中有没有错误发生,同时判断successors(也就是返回的stash)中,如果没有None(也就是上面的stash中的flat.successors)和unconstraints的state存在,之后进去判断是不是有unsat状态,如果有pass,如果连unsat都没有,也就是说什么后继state都没有,就会放入deadended的这个分类中。

下面的那个else中就是表示,如果我们在一开始state_option中定义了save_unsat,就不会把unsat的state  pop掉,如果没有定义我们的unsat state就会pop掉了。

下面就是这个for循环的最后的一部分,

就是相当于将当前state的产生的所有stash中的所有后继state,放入整个for循环(step函数中)中定义的bucket中。

之后就是跳出for循环之后step这个函数的最后一部分

self._clear_states(stash=stash)这个函数截图

debug可以知道如果我们stash是active的话,self._stashes[_stash][:]这句话就是将我们这个已经运行过的active中的state都删除掉,因为我们已经运行结束了,这些state已经没有用处了。

之后的for循环就是将我们的bucket中的东西全都存入相应的stash中去。

这一段应该很好理解,最后的if判断就是我们的参数中的step_func是不是None,如果我们传入的step_func这个函数,我们就要对其进行操作了。返回self。

之后会跳转到我们自己编写的step函数的return simgr.step()那个地方,之后一直返回到sim_manager的run函数中。

第一个循环判断n,n就是你最多循环次数的判断,第二个就是self.complete()的判断的一个条件,以及_stashes[stash(active)]的有没有state,如果条件都满足就会进入下一个阶段,至此循环结束。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值