核心概念

您所在的位置:网站首页 DDG是什么手册 核心概念

核心概念

2024-07-13 00:18| 来源: 网络整理| 查看: 265

来源 anhkgg 浏览 623 扫码 分享 2022-05-01 21:25:19 核心概念基本属性加载器The factoryBlocksStates模拟管理器(Simulation Managers)分析(Analyses)Now what?核心概念

在开始使用angr之前,您需要对一些基本的angr概念以及如何构建一些基本的angr对象有一些基本的了解。

使用angr的第一个操作肯定是加载一个二进制文件生成 project。我们使用/bin/true作为演示。

>>> import angr>>> proj = angr.Project('/bin/true')

在angr中project是控制的基础。你可以使用angr对加载的可执行文件进行分析和模拟。

基本属性

首先,了解一下project的一些基本属性:CPU架构,文件名,入口地址。

>>> import monkeyhex # 数值结果将以十六进制显示>>> proj.arch>>> proj.entry0x401670>>> proj.filename'/bin/true' arch 是archinfo.Arch对象的一个实例,表示表示编译程序的体系结构,本例中是amd64小端模式。它包含了大量有关运行CPU的文书数据,你可以在闲暇时仔细阅读。你通常关心的是arch.bits, arch.bytes (这个是主 Arch 类的一个@property声明), arch.name和arch.memory_endness.entry 是入口地址filename 是二进制文件的绝对路径。 加载器

从二进制文件到虚拟地址空间中的表示非常复杂!我们有个叫CLE的模块来处理这个。CLE的结果称为加载器,通过.loader属性来调用。我们[很快](./loading.md)将详细介绍如何使用,现在只需要直到可以使用它来查看与程序一起加载的共享库和查询加载的地址空间。

>>> proj.loader>>> proj.loader.shared_objects # may look a little different for you!{'ld-linux-x86-64.so.2': , 'libc.so.6': }>>> proj.loader.min_addr0x400000>>> proj.loader.max_addr0x5004000>>> proj.loader.main_object # 主模块>>> proj.loader.main_object.execstack # 是否有可执行堆栈False>>> proj.loader.main_object.pic # 是否位置无关True The factory

angr中有很多类,大多需要实例化的project。为了不让你到处传递project,我们提供了project.factory,有几个方便的你经常会使用的常见对象的构造函数。

本节还将介绍几种基本的angr概念。

Blocks

首先,project.factory.block()用来提取给定地址代码的基本块(basic block)。angr就是以基本块为单位进行代码分析。你可以用Block对象来获取到很多有关代码块的有趣的东西。

>>> block = proj.factory.block(proj.entry) # 提取程序入口的一段代码>>> block.pp() # pretty-print打印反汇编0x401670: xor ebp, ebp0x401672: mov r9, rdx0x401675: pop rsi0x401676: mov rdx, rsp0x401679: and rsp, 0xfffffffffffffff00x40167d: push rax0x40167e: push rsp0x40167f: lea r8, [rip + 0x2e2a]0x401686: lea rcx, [rip + 0x2db3]0x40168d: lea rdi, [rip - 0xd4]0x401694: call qword ptr [rip + 0x205866]>>> block.instructions # 有多少指令?0xb>>> block.instruction_addrs # 每条指令的地址?[0x401670, 0x401672, 0x401675, 0x401676, 0x401679, 0x40167d, 0x40167e, 0x40167f, 0x401686, 0x40168d, 0x401694]

此外,您可以使用Block对象来获取代码块的其他表示形式:

>>> block.capstone # capstone disassembly>>> block.vex # VEX IRSB (这是一个python内部地址,而不是程序地址) States

另外,Project对象只代表程序的一个初始镜像。在执行angr分析时,是通过表示simulated program state的特殊对象SimState进行工作的。

>>> state = proj.factory.entry_state()

SimState包括程序的内存、寄存器、文件系统数据…任何可通过执行改变的“实时数据”都能在SimState中找到。我们将在后面讨论如何与state进行深入交互,但是现在,让我们使用state.regs和state.mem来访问state的寄存器和内存:

>>> state.regs.rip # 获取当前指令指针>>> state.regs.rax>>> state.mem[proj.entry].int.resolved # 将入口点的内存解释为C int

这些不是python的int!而是bitvectors。python的整形和CPU中没有相同的语义,比如包装溢出,所以我们使用bitvector,您可以将其视为由一系列位表示的整数,以表示angr中的CPU数据。注意,每个bitvector都有.length属性来表述位的宽度。

我们将很快了解如何使用它们,但是现在,先看看如何从python int转换为bitvectors,再转换回去: We’ll learn all about how to work with them soon, but for now, here’s how to convert from python ints to bitvectors and back again:

>>> bv = state.solver.BVV(0x1234, 32) # create a 32-bit-wide bitvector with value 0x1234 # BVV stands for bitvector value>>> state.solver.eval(bv) # convert to python int0x1234

您可以将这些位bitvector存储回寄存器和内存,也可以直接存储python整数,它会被转换为适当大小的bitvector:

>>> state.regs.rsi = state.solver.BVV(3, 64)>>> state.regs.rsi>>> state.mem[0x1000].long = 4>>> state.mem[0x1000].long.resolved

mem接口看起来有点让人困惑,因为它使用了一些python的语法糖,下面是使用它的简单方法:

使用array[index]表示指定地址使用.指定内存应解释为 \(常用值:char,short,int,long,size_t,uint8_t,uint16_t …… \)还可以: 设置它的值,可以是bitvector或python int使用.resolved按bitvector来读取值使用.concrete按python int来读取值

有更多高级用法将在稍后介绍!

最后,如果您尝试读取其他寄存器,您可能会遇到一个看起来奇怪的值:

>>> state.regs.rdi

这仍然是64位bitvector,但它不包含数值。 但它有个名字。 这种叫做符号变量(symbolic variable),它是符号执行的基本。 别急!我们将从现在开始会用这两个章节详细讨论这些。

模拟管理器(Simulation Managers)

state表示一个指定时间的程序运行状态,需要有一种方法将它及时传给next点。simulation manager在angr中是主要接口,用于执行,模拟,通过state你可以想怎么调用它干啥都行。为简要介绍,让我们展示如何tick我们之前创建的state转发给几个基本块。

首先,创建一个simulation manager。构造函数可以传入一个state或一个state的列表。

>>> simgr = proj.factory.simulation_manager(state)>>> simgr.active[]

simulation manager可以包含多个stash状态。默认的stash是active,是我们传入的state初始化的。我们可以通过simgr.active[0]来查看更多的状态。

现在,我们会做一些执行。

>>> simgr.step()

刚刚只是执行了一个基本块的符号执行!我们可以再看看active的stash,发现它已经被更新,但它没有修改我们原始的状态。SimState对象执行中是不可变的,你可以安全地在多轮执行中使用单个state。

>>> simgr.active[]>>> simgr.active[0].regs.rip # new and exciting!>>> state.regs.rip # 依然和之前相同

/bin/true不是描述如何用符号执行做有趣事情的一个很好的例子,我们这里不在深入。

分析(Analyses)

angr预先打包了几个内置分析,您可以使用它们从程序中提取一些有趣的信息。 他们是:

>>> 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.CFGEmulated proj.analyses.LoopFinder proj.analyses.VSA_DDG proj.analyses.CFGFast proj.analyses.Reassembler

在本书后面会介绍其中一些内容,但通常你可以通过api 文档来看如何使用一个内置的分析。作为一个非常简短的例子:下面看看如何构建和使用快速控制流图:

# 本来,当我们加载这个二进制文件时,它还将所有依赖项加载到同一个虚拟地址空间中# 大多数分析是不需要的,所以指定auto_load_libs=false>>> proj = angr.Project('/bin/true', auto_load_libs=False)>>> cfg = proj.analyses.CFGFast()# cfg.graph是一个完整CFGNode实例的networkx DiGraph# 可以查看networkx API以了解如何使用它!>>> cfg.graph>>> len(cfg.graph.nodes())951# 使用cfg.get_any_node获取给定地址的CFGNode>>> entry_node = cfg.get_any_node(proj.entry)>>> len(list(cfg.graph.successors(entry_node)))2 Now what?

阅读本页后,您现在应该了解几个重要的angr概念:基本块,状态,位向量(bitvectors),模拟管理器和分析。 除了不能使用angr作为一个很好的调试器之外,你真的做任何有趣的事情! 继续阅读,你将解锁更深层次的能力……

摘要 | 下一节:加载二进制文件

若有收获,就点个赞吧

0 人点赞

上一篇: 下一篇:


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3