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

    基本属性
    首先,我们有一些关于这个项目的基本属性:它的CPU体系结构,文件名以及入口点的地址。
    >>> import monkeyhex # this will format numerical results in hexadecimal
    >>> proj.arch
    <Arch AMD64 (LE)>
    >>> proj.entry
    0x401670
    >>> proj.filename
    '/bin/true'
    arch是archinfo.Arch对象的一个实例,用于编译程序的任何体系结构,在本例中是little-endian amd64。它包含大量关于运行的CPU的文书数据,您可以在闲暇时阅读这些数据。你关心的常见问题是arch.bits,arch.bytes(其中一个是主要Arch类的@property声明),
    arch.name和arch.memory_endness。
    entry是二进制的入口点!
    filename是二进制文件的绝对文件名
     
     
    The loader(加载器)
     
    从二进制文件加载到在虚拟地址空间中非常复杂!我们有一个叫CLE的模块来处理这个问题。 CLE的结果,称为加载程序,在.loader属性中可用。我们将详细介绍如何尽快使用它,
    但是现在只要知道你可以用它来查看angr加载程序时同时加载的共享库,并对加载的地址空间进行基本的查询。
     
    >>> proj.loader
    <Loaded true, maps [0x400000:0x5004000]>
     
    >>> proj.loader.shared_objects # may look a little different for you!
    {'ld-linux-x86-64.so.2': <ELF Object ld-2.24.so, maps [0x2000000:0x2227167]>,
    'libc.so.6': <ELF Object libc-2.24.so, maps [0x1000000:0x13c699f]>}
     
    >>> proj.loader.min_addr
    0x400000
    >>> proj.loader.max_addr
    0x5004000
     
    >>> proj.loader.main_object # we've loaded several binaries into this project. Here's the main one!
    <ELF Object true, maps [0x400000:0x60721f]>
     
    >>> proj.loader.main_object.execstack # sample query: does this binary have an executable stack?
    False
    >>> proj.loader.main_object.pic # sample query: is this binary position-independent?
    True
     
     
    The factory
     
    Angr中有很多类,其中大部分需要实例化一个项目。而不是让你到处将项目作为参数传递,我们提供project.factory,它有几个方便的常用对象的构造函数,你会经常使用。
    本节还将介绍几个基本的angr概念。
     
    Blocks
     
    angr分析代码是以基本块(在编译器构造中,基本块是一个直线代码序列,除了入口外没有分支,除了出口处没有分支)为单位。
    首先,project.factory.block( ),它用来从给定的地址提取一个基本的代码块。你将得到一个Block对象,它可以告诉你关于代码块的很多有趣的事情:
     
    >>> block = proj.factory.block(proj.entry) # lift a block of code from the program's entry point
    <Block for 0x401670, 42 bytes>
     
    >>> block.pp() # pretty-print a disassembly to stdout
    0x401670: xor ebp, ebp
    0x401672: mov r9, rdx
    0x401675: pop rsi
    0x401676: mov rdx, rsp
    0x401679: and rsp, 0xfffffffffffffff0
    0x40167d: push rax
    0x40167e: push rsp
    0x40167f: lea r8, [rip + 0x2e2a]
    0x401686: lea rcx, [rip + 0x2db3]
    0x40168d: lea rdi, [rip - 0xd4]
    0x401694: call qword ptr [rip + 0x205866]
     
    >>> block.instructions # how many instructions are there?
    0xb
    >>> block.instruction_addrs # what are the addresses of the instructions?
    [0x401670, 0x401672, 0x401675, 0x401676, 0x401679, 0x40167d, 0x40167e, 0x40167f, 0x401686, 0x40168d, 0x401694]
     
    此外,您可以使用Block对象来获取代码块的其他表示形式:
     
    >>> block.capstone # capstone disassembly
    <CapstoneBlock for 0x401670>
    >>> block.vex # VEX IRSB (that's a python internal address, not a program address)
    <pyvex.block.IRSB at 0x7706330>
     

     

    States

    Project对象只代表程序的“初始化映像”。当你用angr执行执行时,使用的是一个代表模拟程序状态的特定对象 (SimState)。
     
    >>> state = proj.factory.entry_state()
    <SimState @ 0x401670>
    一个SimState包含一个程序的内存,寄存器,文件系统数据...任何会在执行中改变的“实时数据”都会在这个state中。稍后我们将介绍如何与状态进行深入交互,但现在让我们使用state.regs和state.mem来访问这个状态的寄存器和内存:
     
    >>> state.regs.rip # get the current instruction pointer
    <BV64 0x401670>
    >>> state.regs.rax
    <BV64 0x1c>
    >>> state.mem[proj.entry].int.resolved # interpret the memory at the entry point as a C int
    <BV32 0x8949ed31>
    这里是如何从python ints转换为bitvectors,然后再返回:
    >>> 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
    您可以将这些位向量存储回寄存器和内存,也可以直接存储一个python整数,并将其转换为适当大小的位向量:
     
    >>> 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>
    使用array [index]表示法指定一个地址
    使用<type>来指定内存应该被解释为<type>(通用值:char,short,int,long,size_t,uint8_t,uint16_t ...)
    从那里,你可以:
        存储一个值,无论是一个bitvector或一个python int
        使用.resolved将该值作为bitvector
        使用.concrete将该值作为python int
     
    如果尝试去获取其他寄存器,可能会遇到看起来很奇怪的值:
    >>> state.regs.rdi
    <BV64 reg_48_11_64{UNINITIALIZED}>
    它仍旧是一个64bit 的bitvector,但它不包含一个数值,而是一个名称,叫做symbolic variable(符号变量),它是符号执行的基础。
     
     
    Simulation Managers(模拟化管理器)
     
    如果一个state表示处在某个时间点的程序,那么一定会有方法使它达到下一个时间点。Simulation Manager是angr中的主要接口,用于进行执行或者说模拟。
     
    首先,我们创建simulation manager,
    >>> simgr = proj.factory.simgr(state) # TODO: change name before merge
    <SimulationManager with 1 active>
    >>> simgr.active
    [<SimState @ 0x401670>]
    造函数会参数一个state或state列表。
     
     
    simulation manager含有几个stash,默认的stash,active,由传入的state初始化。
     
    我们开始执行
    >>> simgr.step()
     
    可以再次查看存活的stash,注意到它已经改变,而且这并不会修改原来的state,SimState对象在执行过程中透明。可以安全的使用单个state作为任意一次执行的起点。
    >>> simgr.active
    [<SimState @ 0x1020300>]
    >>> simgr.active[0].regs.rip # new and exciting!
    <BV64 0x1020300>
    >>> state.regs.rip # still the same!
    <BV64 0x401670>
     
     
    Analyses
     
    angr预先打包了几个内置analyses,可以利用它们来获取程序中一些有趣的信息:
    >>> proj.analyses. # Press TAB here in ipython to get an autocomplete-listing of everything:
    proj.analyses.BackwardSlice        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.CFGAccurate          proj.analyses.LoopFinder             proj.analyses.VSA_DDG
    proj.analyses.CFGFast              proj.analyses.Reassembler
     
    如何构建并使用一个快速控制流程图:
    # 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

    翻译自:https://docs.angr.io

     
     
  • 相关阅读:
    P2634 [国家集训队]聪聪可可
    P2051 [AHOI2009]中国象棋
    java集成工具的简单总结
    java-web中的web.xml中的servlet和servlet-mapping标签,及网页处理流程
    ecplist中快速添加set get方法
    Spring创建容器之new ClassPathXmlApplicationContext错误
    设计模式之工厂模式
    java-web项目的eclipse里面引入jar包
    DES原理及代码实现
    Linux网络篇,ssh原理及应用
  • 原文地址:https://www.cnblogs.com/fancystar/p/7851736.html
Copyright © 2011-2022 走看看