符号执行-Angr实践

  1. 关于Angr
    Angr是一个利用python开发的二进制程序分析框架,我们可以利用这个工具尝试对一些CTF题目进行符号执行来找到正确的解答,即flag。当然,要注意的是符号执行的路径选择问题到现在依旧是一个很大的问题,换句话说也就是当我们的程序存在循环时,因为符号执行会尽量遍历所有的路径,所以每次循环之后会形成至少两个分支,当循环的次数足够多时,就会造成路径爆炸,整个机器的内存会被耗尽(我们这次分析的程序只有两个分支,不会存在这个问题)。

准备:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

官方建议使用python虚拟环境来安装和使用angr。 几个angr的依赖项(z3,pyvex)需要从原始代码分叉的本机代码库,如果已经安装了libz3或libVEX,绝对不应该用angr的代码覆盖官方共享对象。为了避免覆盖等问题,一般建议在虚拟环境中使用,由于使用虚拟机演示,所以可以忽略这个问题,使用完毕后如果出现问题恢复镜像即可,如果采用物理机演示,建议在python环境中操作。

要分析的文件为fauxware,已经放在home目录下
首先创建一个proiject
在这里插入图片描述
类似于上面的流程,可以查看CPU 架构(arch)、文件路径(filename)、入口地址(entry)
在这里插入图片描述
angr 的 CLE 模块用于加载二进制程序到虚拟地址空间。加载器(loader)作为项目的一个属性可用于查看与二进制程序一起加载的共享库,并且可在加载地址空间进行查询操作
查看内存空间中的共享库
在这里插入图片描述
查看加载到内存空间的主要二进制文件、查询栈是否可执行、查询是否为位置无关代码
在这里插入图片描述

angr 中有很多类,其中大部分需要在项目中进行实例化。通过 project.factory 可以方便地使用一些常用的对象
使用 project.factory.block 可从给定的地址提取代码块。
在这里插入图片描述
还可将 block 转化为 VEX 中间语言形式。
在这里插入图片描述
Project 中保存的是程序的初始内存映像,二进制程序执行后的状态由 SimState(simulated program state)表示。SimState 包含程序执行时的状态数据,比如进程内存、寄存器和文件数据等。下图演示的是分别获取寄存器的值、获取程序入口地址处内存(以int类型解析)
在这里插入图片描述
simulation managers是 angr 中用于执行和模拟程序的接口,可以管理多个程序state。stash 为包含多个同类状态的列表,默认执行的 stash 为active。模拟管理器中使用 .step() 以基本 block 为单位运行。
在这里插入图片描述
和分析/bin/true一样,同样可以生成程序的控制流图
在这里插入图片描述
同样是不加载共享库,打印出节点数0x5c,即十进制的92个
在这里插入图片描述
对fauxware的黑盒分析到此告一段落,接下来去看看源码

关注authenticate函数
由注释的提示可知,存在后门,只要密码输入为SOSNEAKY,就可以验证成功
在这里插入图片描述
根据authenticate的判断逻辑结合angr的工作原理,我们可以知道
当程序运行到 if (strcmp(password, sneaky) == 0) 分支时会产生两个状态,其中一个状态将会包含用户输入正确后门密码的约束条件。
使用IDA分析
先判断文件格式
在这里插入图片描述
IDA载入
在这里插入图片描述
找到main函数
在这里插入图片描述
F5反编译
在这里插入图片描述
双击authenticate函数
在这里插入图片描述
可以看到在if判断中是跟着sneaky
双击查看
在这里插入图片描述
可以看到sneaky的数据就是后门密码。
至于判断之后分叉的两个状态可以切换到view-A,然后空格键切换到graph overview
在这里插入图片描述
找到authenticate之后双击查看执行流图
在这里插入图片描述
上图显示的就是authenticate执行后的两个分支,也即angr分析时的state1和state2

使用angr分析时可以清楚地看到两个状态
在这里插入图片描述
一直执行直到出现两个分支时停下
在这里插入图片描述
获取进入特定分支, 需要往 stdin 输入的数据
可以看到这里如果要进入返回 1 的分支( state1 ),只要往 stdin 输入 SOSNEAKY ,从而认证通过,这就是前面分析源码时判断的后门密码。
angr 重写了一些 libc 的函数,比如获取 stdin 数据,会返回符号量,用于符号执行,在某个状态下可以使用 state1.posix.dumps(0) 获取进入该状态时 stdin 需要输入的数据 (0表示的就是 stdin, 1 则是 stdout ),所以上面我们使用state.posix.dumps来获取。
以上是我们为了便于理解angr的使用才一步步来分析,如果熟练掌握的话可以直接写脚本获取后门密码
代码
在这里插入图片描述
前面提到1表示stdout,脚本首先判断分支后的哪个状态会打印出welcome,然后打印出进入该状态需要输入的数据。

运行
在这里插入图片描述

运行
在这里插入图片描述
随意输入会报错
在这里插入图片描述
输入后门密码即可通过判断

参考
1.官方手册https://docs.angr.io/

猜你喜欢

转载自blog.csdn.net/yalecaltech/article/details/88753923