zoukankan      html  css  js  c++  java
  • angr学习(二)

    Surveyor
     
    作为符号执行的引擎,它跟踪可执行的路径,标志出向前进的路径和倒退的路径,并且优化资源配置.
    surveyor类并不直接使用,一般会被开发者子类化后来用作他们自己的分析。
    最常见的符号分析(类似探索从A达到B,并避开C)已经在Explore类中实现。
     
     
    Explorer
    surveyors.Explorer 是surveyor的子类,用来执行符号搜索。
    它可以被指定从哪儿开始,执行到哪儿,避开哪儿,和跟踪哪条路径。
    它也会尝试避免死循环。
    import  angr
     
    b= angr.Project('.../../...')
     
    一个surveyor对象在程序的入口开始执行,通过“Project.initial_exit”来退出。
    它通过使用“Project.initial_state”来创建一个状态块。
    经常使用的SimExit,创建了一个自定义状态块,能够提供“start”的可选参数,或者“starts”的可选参数列表。
    e=b.surveyors.Explorer()
    现在我们可以运行几步了,打印一个Explorer对象来知道现在有多少条可行路径。
    print e.step()
    你可以使用'Explorer.run'来运行一段时间。
    e.run(10)
    不指定时间时,explorer对象一直运行知道跑完所有路径(但对于大部分程序来说不是这样的)。在本例子中,我们不会遇到,程序时并不无限循环。
    e.run()
    我们可以知道哪条路径可通,哪条是死路(不提供可行退出),哪条出错。但在一些实例中,一条给定路径存在多种情况(即出错又无法退出)。
    print "%d paths are still running" % len(e.active)
    print "%d paths are backgrounded due to lack of resources" % len(e.spilled)
    print "%d paths are suspended due to user action" % len(e.suspended)
    print "%d paths had errors" % len(e.errored)
    print "%d paths deadended" % len(e.deadended)
    到目前为止,所有我们讨论的都适用于所有的Surveyors。但是,更棒的是一个Explorer对象可以被告知要寻找时,或避免去某个区块。
    例子:
    创建一个Explorer对象尝试去找到0x4006ed,并避开0x4006fd和0x4006aa。
    e=p.surveyors.Explorer(find=(0x4006ed,),avoid = (x04006aa,0x4006fd))
    e.run()
     
    打印我们发现的后门和避开了多少条路径
    if len(e.found) >0:
        print "found backdoor path:",e.found[0]
     
    print "Avoided %d paths" % len(e.avoided)
     
    Caller
     
    Caller使被调函数更简单得计算出程序到底做了些什么 
    加载程序:
    b = angr.Project('../../..')
     
    初始化state,并得到我们的username和password 的符号表达式为了之后的检查。这里,我们多伪造一位因为我们知道username和password都是8字节。
    p=b.factory.path()
    username= p.state.memory.load(0x1000,9)
    password = p.state.memory.load(0x2000,9)
    调用关键函数,把username和password的指针传入
    c=b.surveyors.Caller(0x400664,(0x1000,0x2000),start=p)
    查看不同路径的返回
    print tuple(c.iter_returns())
     
    其中返回1的路径
    print tuple(c.iter_returns(solution=1))
    现在我们能看到要到达目标点所需要的username和password。
    'c.map_se' 调用 state.se.any_n_str(或者所提供的任意其他函数)
    credentials = username.concat(password)
    tuple(c.map_se('any_n_str',credentials,10,solution =1))
    

      

     
    Inerrupting Surveyors
    Surveyor对象保存它的内核状态在每个tick之后.在IPython中,你应该能够暂停一个 surveyor用Ctrl-C,然后检查到目前为止有什么结果,但这是一个不好的做法。有两个简洁的官方方式:SIGUSR1和SIGUSR2。
    如果你发送SIGUSR1到运行surveyor的python进程,它会导致主循环 Surveyor.run()在当前Surveyor.step()结束时终止。然后可以分析结果。要继续运行surveyor,要调用angr.surveyor.resume_analyses()(清除 “signalled”标志),然后调用surveyor的run()函数。因为SIGUSR1会导致run()返回,这在脚本化分析中很少有用,因为程序的其余部分将在run()之后运行, 返回。相反,SIGUSR1意味着提供一个干净的替代Ctrl-C。 另一方面,将SIGUSR2发送到python进程会导致run()调用ipdb断点 后每个步骤()。这允许您调试,然后继续您的程序。确保运行angr.surveyor.disable_singlestep(),然后继续清除“信号”标志。
     
     
     
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    path_group
    path_group允许我们监视多条路径以一个确切的方式。路径被设置为“stashes”,我们可以控制前进、步过、合并,随意移动。
    有不同种类的“stashes”。
    Paths:
    我们可以以不同的规律来跑不同的stash,并使其一起汇合。
    import angr
     
    p=angr.Project('...',load_option={'auto_load_lib':false})
    pg=p.factory.path_group()

    当有可行路径时

    while len(pg.active) > 0:
        pg.step()
     
    print (pg)
    当我我们遇到死路后,我们怎么做?
    path = pg.deadended[0]
    Print('path length: {0} steps'.format(path.length))
    得到路径步骤:
    Print('Trace:')
    For step in path.trace:
        Print(step)
    得到路径中的限制:
    print ('There are %d constraints.' % len(path.state.se.constraints))
     
    得到在结束时的内存状态
    print ('rax:{0}'.format
    (path.state.regs.rax))
     
    assert path.state.se.any_int(path.state.regs.rip)==path.addr
     
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    Pathgroup.Explorer
    pathgroup被认为会取代 surveyors.Explorer,它更灵活更有效。
    当path_group.Explorer运行中得到find区块,多条路径将会运行步进直到发现我们所要寻找的地址。路径到达avoided地址,如果发生,将会被记录在avoided stash中。如果一个行进的的路径到达一个我们感兴趣的地址,它会被stash进found stash,并且其他路径继续行进。我们可以研究这个found 路径,或者舍弃它让其他路径继续。
     
    载入二进制文件
    p=angr.Project('../../..')
     
    我们创建一个path group
    pg=p.factory.path_group()
     
    现在,我们符号化执行直到发现一条路径符合我们的条件
    pg.explore(find=lambda p:"Congrats" in p.state.posix.dumps(1))
     
    现在,我们从状态块中得到了flag
    s=pg.found[0].state
    print s.posix.dumps(1)
     
    flag=s.posix.dumps(0)
    print (flag)
     

    在path_group执行时,路径会被归为不同类型的stash

    stash        描述
    active  包含了默认执行的路径(除非一个替换的stash被指定给path_group.step())
    deadended  一条进入deadended stash的路径,是指它因为一些原因而无法继续执行,包括没有有效指令、无效的指令指针、unsat状态的后续。
    found 一条到达found stash 的路径,是指它满足path_group.explore的find节所给出的条件
    avoided 是指它满足path_group.explore的avoid节所给出的条件
    pruned  当使用LAZY_SOLVES时,路径不会被检查是否会满足,除非它很重要。当state未指定LAZY_SOLVES时,路径一旦状态变为unsat后,层次就被划分了。所有从这个点派生的路径会被删除并把这个路径作为pruned stash。
    errored 当引起python异常时执行,这意味着angr或者自己的代码中有错误。
    unconstrained 如果path_group的构造函数被指定save_unconstrained参数,路径就确定为无约束的(其中指令指针被用户数据或一些其他符号数据源所控制)放在此处
    unsat 如果path_group的构造函数被指定save_unsat参数,路径就确定为不可满足的(他们具有矛盾的约束条件,例如同时输入“AA”和“BB”)放在此处
    你可以使用path_group.move函数来在不同的stash中移动路径。这个函数接受很多参数来控制这些路径移动。
  • 相关阅读:
    [公链观点] BTC 1.0, ETH 2.0, EOS 3.0, Dapp, WASM, DOT, ADA, VNT
    [FAQ] chrome.runtime.onMessage 问题, Unchecked runtime.lastError: The message port closed before a response was received
    [FAQ] Composer, Content-Length mismatch
    [PHP] Laravel 依赖注入使用不当引起的内存溢出
    [PHP] 浅谈 Laravel auth:api 不同驱动 token 和 passport 的区别
    [PHP] 自定义 laravel/passport 的误区讲解
    [Tools] Kali Linux 高清屏扩大系统字体、BurpSuite、OpenVAS
    [NoSQL] 从模型关系看 Mongodb 的选择理由
    [quacker] Browser Extension to Clean Website ADs in Quasar BEX
    [FE] Quasar BEX 预览版指南
  • 原文地址:https://www.cnblogs.com/fancystar/p/7863192.html
Copyright © 2011-2022 走看看