当前位置: 首页 > news >正文

Angr符号执行初步学习

angr符号执行框架,是我一直想要理解学习的,今天就来实际学习体验一下。

根据网上教的,应该是在GitHub - jakespringer/angr_ctf 网站上面下载对应的习题,编写对应的python进行练习。

前置要求:安装angr库,我已经满足,接下来就开始进行捣鼓。

angr的原理我也不太能解释清楚,所以直接开干吧。(默认python代码均引入angr库)

因此,使用 angr 一般分为如下步骤:

  1. 创建 Project,预设 state
  2. 创建位向量和符号变量,保存在内存/寄存器/文件或其他地方(简单的题目直接可以省略)
  3. 将 state 添加到 SM 中
  4. 运行,探索满足条件的路径
  5. 约束求解获取执行结果

1-angr-find

用这个作为入门吧。分析一下代码:

int __cdecl main(int argc, const char **argv, const char **envp)
{int i; // [esp+1Ch] [ebp-1Ch]char s1[9]; // [esp+23h] [ebp-15h] BYREFunsigned int v6; // [esp+2Ch] [ebp-Ch]v6 = __readgsdword(0x14u);printf("Enter the password: ");__isoc99_scanf("%8s", s1);for ( i = 0; i <= 7; ++i )s1[i] = complex_function(s1[i], i);if ( !strcmp(s1, "JACEJGCS") )puts("Good Job.");elseputs("Try again.");return 0;
}

根据学习的知识,首先应该创建一个project。

p = angr.Project("./00",auto_load_libs='false')

为了提高效率,不自动加载依赖库。

然后应该创建一个state,就是作为一个镜像(Project 仅完成二进制文件加载,执行操作实际围绕 SimState 对象(程序状态)开展。 类似于做了一个镜像)

要创建状态,需借助 Project 对象的 factory,它还可用于创建模拟管理器、基本块

state=p.factory.entry_state()

上述方式只是预设了程序开始分析时的状态,我们要分析程序就必须要让它到达下一个状态,这就需要
模拟管理器的帮助(简称 SM)

sm = p.factory.simgr(state)

可以通过 step() 方法来让处于 active 的 state 执行一个基本块,这种操作不会改变 state 本身(类比 docker)state只是一个镜像而已,进入SM才有执行的可能性:

可以使用 explorer 方法去执行某个状态,直到找到目标指令或者 active 中没有状态为止,它有如下参数:

  • find:传入目标指令的地址或地址列表,或者一个用于判断的函数
  • avoid:传入要避免的指令的地址或地址列表,或者一个用于判断的函数,用于减少路径

第一关还是比较简单的,下面就是脚本:

import angr
p = angr.Project("./00")
state=p.factory.entry_state()
sm = p.factory.simgr(state)
sm.explore(find=0x8048675)
if sm.found:print(sm.found[0].posix.dumps(0))

2-angr-avoid

这一关卡需要进行avoid。因为主函数太大了!为什么主函数大?一个函数“avoid me”在主函数被反复调用。只需要增加avoid参数即可。

import angr
p = angr.Project("./01")
state=p.factory.entry_state()
sm = p.factory.simgr(state)
sm.explore(find=0x80485B5,avoid=0x80485A8)
if sm.found:print(sm.found[0].posix.dumps(0))

3-angr-find-condition

这里引入新的概念:利用函数,传给find和avoid,什么意思呢?

函数的return表示“找到这个函数的条件”dump(1)表示标准输出。

这是一个具体实例:

def find(state):return b'Good Job.' in state.posix.dump(1)#标准输出
def avoid(state):return b'Try again.' in state.posix.dump(1)

程序在正确的时候会提示字符串,所以可以从这里入手。给explore传参只需要传递函数名即可

import angr
p = angr.Project("./02")
state=p.factory.entry_state()
sm = p.factory.simgr(state)
def find(state):return b'Good Job.' in state.posix.dumps(1)
def avoid(state):return b'Try again.' in state.posix.dumps(1)
sm.explore(find=find,avoid=avoid)
if sm.found:print(sm.found[0].posix.dumps(0))

4-angr_symbolic_registers

开始介绍怎么给寄存器传入对应的初始量了。这一题很有意思,输入做了拆分,通过ecx寄存器做中间人将值最终放在eax、ebx、edx寄存器。

所以我们需要求出三个未知量,自然需要做出调整,这里介绍angr里面的变量类型。我们想要从程序的某个地方开始执行,就需要用到blank_state(addr=0xxxx)。我们可以跳过拆分输入的环节,直接设置符号变量让他求解。

BVS设置为32位,因为一个Int占32位。

不要忘记再给寄存器传入我们的参数,按照源程序的顺序给即可。

import angr
import claripy
p = angr.Project("./03")
state=p.factory.blank_state(addr=0x8048980)
x = claripy.BVS("x",32)
y = claripy.BVS("y",32)
z = claripy.BVS("z",32)
state.regs.eax=x
state.regs.ebx=y
state.regs.edx=z
sm = p.factory.simgr(state)
def find(state):return b'Good Job.' in state.posix.dumps(1)
def avoid(state):return b'Try again.' in state.posix.dumps(1)
sm.explore(find=find,avoid=avoid)
if sm.found:x=sm.found[0].solver.eval(x)y=sm.found[0].solver.eval(y)z=sm.found[0].solver.eval(z)print(f"{hex(x)} {hex(y)} {hex(z)}")

说实话,跟着教程走还是比较好理解的,记住关键的函数名字即可。

5-angr_symbolic_stack

这个题目开始模拟栈。

这里的scanf的参数又直接压到了栈上。

我们只需要关心求解的未知数在栈上的布局即可,其他的栈内容无需操心,也不会影响大局。

还需要知道的是,blank_state会初始化esp,但是不会初始化ebp,我们可以用esp给ebp赋值,进而初始化栈。

根据ida的栈布局,确定esp相对位置。刚开始肯定是要esp刚好指向两个未知变量栈的下面。这样子push完之后也恰好满足原函数的栈布局。

import angr
import claripy
p = angr.Project("./04")
state=p.factory.blank_state(addr=0x08048697)
x = claripy.BVS("x",32)
y = claripy.BVS("y",32)
state.regs.ebp=state.regs.esp
state.regs.esp -= 8#根据ida确认
state.stack_push(x)
state.stack_push(y)
sm = p.factory.simgr(state)
def find(state):return b'Good Job.' in state.posix.dumps(1)
def avoid(state):return b'Try again.' in state.posix.dumps(1)
sm.explore(find=find,avoid=avoid)
if sm.found:x=sm.found[0].solver.eval(x)y=sm.found[0].solver.eval(y)print(f"{x} {y} ")

6-angr_symbolic_memroy

操作内存。这个程序直接使用memset函数在bss段开辟了一些地方存储输入的数据,这就需要控制内存

读写内存:state.memory.store/load。只需要往对应内存地带写入数据即可。

说明:可以利用store配合寄存器寻址,如state.regs.ebp-0x1c,也可以识别得到。

还需要注意的是,这里的是字符串,因此需要用cast_to强制转换,并需用 decode() 转换为可读字符串

import angr
import claripy
p = angr.Project("./05")
state=p.factory.blank_state(addr=0x08048601)
x = claripy.BVS("x",64)#这里需要改为64位,因为是8个字符
y = claripy.BVS("y",64)
z = claripy.BVS("z",64)
a = claripy.BVS("a",64)
state.memory.store(0xA1BA1C0,x)
state.memory.store(0xA1BA1C8,y)
state.memory.store(0xA1BA1D0,z)
state.memory.store(0xA1BA1D8,a)
sm = p.factory.simgr(state)
def find(state):return b'Good Job.' in state.posix.dumps(1)
def avoid(state):return b'Try again.' in state.posix.dumps(1)
sm.explore(find=find,avoid=avoid)
if sm.found:x=sm.found[0].solver.eval(x,cast_to=bytes).decode()y=sm.found[0].solver.eval(y,cast_to=bytes).decode()z=sm.found[0].solver.eval(z,cast_to=bytes).decode()a=sm.found[0].solver.eval(a,cast_to=bytes).decode()print(f"{x} {y} {z} {a}")

文章转载自:

http://X3BCIzOj.grqLc.cn
http://fg32SL1l.grqLc.cn
http://sceN3Euv.grqLc.cn
http://Oq6Y0eeL.grqLc.cn
http://KmVnWc9b.grqLc.cn
http://ZVhYpe8N.grqLc.cn
http://b55rhMZv.grqLc.cn
http://J9dW4Hyq.grqLc.cn
http://Fy4z0jhN.grqLc.cn
http://24UAXrYT.grqLc.cn
http://ErniOkaj.grqLc.cn
http://R0KWLaiX.grqLc.cn
http://RgGKnRlR.grqLc.cn
http://arIpLI9n.grqLc.cn
http://jz13hnt9.grqLc.cn
http://qPLy9BYI.grqLc.cn
http://qOgaYA5w.grqLc.cn
http://I96mnPUi.grqLc.cn
http://dOvn5qup.grqLc.cn
http://rUPJAwAa.grqLc.cn
http://SIzBwIwc.grqLc.cn
http://zXWSFrQq.grqLc.cn
http://ONhcR1Mj.grqLc.cn
http://Ap0Qf1hl.grqLc.cn
http://P19L6fD7.grqLc.cn
http://TT6ANu5W.grqLc.cn
http://Cuemw0df.grqLc.cn
http://6VIF2v6e.grqLc.cn
http://lAPBCkpd.grqLc.cn
http://HQLslE1Q.grqLc.cn
http://www.dtcms.com/a/377706.html

相关文章:

  • Shell编程之正则表达式与文本处理工具
  • 软考系统架构设计师之UML统一建模语言
  • malloc概述
  • Nginx 实战系列(九)—— LVS负载均衡集群与DR模式部署指南
  • 利用美团龙猫用libxml2编写XML转CSV文件C程序
  • NJet支持使用json格式的配置文件了
  • 平时只会CRUD,没有高质量项目经验,我该怎么办
  • Vue项目创建方式(多种)
  • PMM:一款开源的数据库监控与管理工具
  • pyinstaller打包多个文件成一个exe
  • JavaScript逆向非对称加密算法
  • 基于EB_S32K3XX芯片的EMIOS_PWM的输出_1
  • 计算机毕设 java 高校会议信息管理系统的设计与实现 基于 SSM 框架的高校会议服务平台 Java+MySQL 的会议室预约与管理系统
  • Git 初识
  • 安全用电管理系统助力银行以全链路监测
  • 3.远程控制网络编程的设计上
  • 存算一体芯片生态评估:从三星PIM到知存科技WTM2101
  • 智联未来 点赋科技
  • SpringBoot项目健康检查端点返回为down排查思路
  • yolov8(yolov11)目标识别使用Tensorrt推理-2.0(C++Api)
  • 《Java中的IO流》
  • sql语句练习
  • 《深度学习的核心公式》
  • 划痕缺陷检测:3类成因,对应3套打光方案
  • 摆动序列:如何让数组“上下起伏”地最长?
  • 模型 公地悲剧
  • 深入理解 Android targetSdkVersion:从 Google Play 政策到依赖冲突
  • DDNS动态域名解析服务:原理与工具详解全攻略,外网畅访内网设备用自定义固定域名
  • 【系统分析师】第20章-关键技术:信息物理系统分析与设计(核心总结)
  • 批量更新数据:Mybatis update foreach 和 update case when 写法及比较