【记录】Angr|Angr 标准库函数替换怎么看哪些库函数被Angr支持?

文章目录

  • 前言
  • 分析
    • 什么是库函数替换?
      • 为什么需要库函数替换?
    • 如何查找支持的库函数
      • 官方支持列表
      • 目录结构说明
    • 常用的替换包括哪些?
      • 1. 字符串处理函数
      • 2. 内存管理函数
      • 3. 文件操作函数
    • 高级技巧
      • 1. 自定义库函数实现
      • 2. 条件替换
    • 常见问题与解决方案详解
      • 1. 找不到合适的替换函数
        • 问题表现
        • 解决方案
          • 1.1 源码分析法
          • 1.2 自定义实现示例
          • 1.3 使用近似替换
      • 2. 替换后行为异常
        • 问题表现
        • 解决方案
          • 2.1 函数签名检查
          • 2.2 约束条件调整
          • 2.3 状态空间控制
      • 3. 性能问题
        • 问题表现
        • 解决方案
          • 3.1 简化替换函数
          • 3.2 深度限制
          • 3.3 优化约束条件
      • 实用建议
      • 最佳实践总结
    • 总结

前言

我在学习 Angr,这里会记录一些琐碎的、在中文引擎里一搜没找到解法的问题。Angr 是一种符号执行工具。

我的学习内容:
博主链接:Angr 使用技巧速通笔记(二) | TokameinE - 雨声淅淅沥沥,犬吠永不止息
Github 教程链接:https://github.com/jakespringer/angr_ctf

本博客是学习到 13_angr_static_binary 时产生的疑惑。

分析

什么是库函数替换?

在符号执行过程中,为了更好地控制执行流程和状态空间,Angr 会使用自己实现的版本来替换程序中的标准库函数调用。这些替换函数通常是原始函数的简化版本,专门为符号执行优化设计。

为什么需要库函数替换?

  1. 性能优化: 原始库函数可能过于复杂,会导致状态空间爆炸
  2. 行为控制: 可以更精确地控制函数行为,便于分析
  3. 符号执行支持: 确保函数可以正确处理符号值
  4. 跨平台兼容: 提供统一的函数行为,减少平台差异

如何查找支持的库函数

首先,Angr 标准库函数替换怎么看哪些库函数被Angr支持?这个问题 Angr_ctf 题解里面写了,提供了官方支持列表。

官方支持列表

Angr 的所有支持库函数都可以在其 GitHub 仓库中找到:
https://github.com/angr/angr/tree/master/angr/procedures

目录结构说明

angr/procedures/
├── libc/           # C标准库函数
├── posix/          # POSIX系统调用
├── win32/          # Windows API
├── linux_kernel/   # Linux内核函数
└── ...

进而不由产生其他疑问:

  1. 这么多库函数怎么知道自己想要的是哪个?
  2. 常用的替换包括哪些?

常用的替换包括哪些?

常用的替换有哪些?
Angr替换库函数的种类相对广泛,常见的包括:

  • 内存相关函数:如mallocfreecalloc等。
  • 字符串操作函数:如strlenstrcpystrncpy等。
  • 文件操作函数:如openreadwriteclose等。
  • 系统调用:如execveexit等。
  • 时间和日期相关:如timegmtimelocaltime等。

这些替换的函数一般都提供了简化版或精简版的实现,方便Angr进行符号执行和模拟。

1. 字符串处理函数

# 示例: 替换 strlen 函数
import angrdef analyze_strlen():proj = angr.Project('./target_binary')# 手动替换 strlenproj.hook_symbol('strlen', angr.SIM_PROCEDURES['libc']['strlen']())# 模拟执行state = proj.factory.entry_state()simgr = proj.factory.simulation_manager(state)simgr.explore()

常见字符串函数替换:

  • strlen: 字符串长度计算
  • strcpy: 字符串复制
  • strncpy: 限制长度的字符串复制
  • strcat: 字符串拼接

2. 内存管理函数

# 示例: 替换 malloc 和 free
def analyze_memory():proj = angr.Project('./target_binary')# 替换内存分配函数proj.hook_symbol('malloc', angr.SIM_PROCEDURES['libc']['malloc']())proj.hook_symbol('free', angr.SIM_PROCEDURES['libc']['free']())

常见内存函数:

  • malloc: 动态内存分配
  • calloc: 分配并清零内存
  • realloc: 重新分配内存
  • free: 释放内存

3. 文件操作函数

# 示例: 模拟文件操作
def analyze_file_ops():proj = angr.Project('./target_binary')# 替换文件操作函数proj.hook_symbol('fopen', angr.SIM_PROCEDURES['libc']['fopen']())proj.hook_symbol('fread', angr.SIM_PROCEDURES['libc']['fread']())proj.hook_symbol('fwrite', angr.SIM_PROCEDURES['libc']['fwrite']())proj.hook_symbol('fclose', angr.SIM_PROCEDURES['libc']['fclose']())

高级技巧

1. 自定义库函数实现

有时候 Angr 提供的默认实现可能不满足需求,我们可以自定义实现:

class CustomStrlen(angr.SimProcedure):def run(self, str_addr):# 自定义 strlen 实现strlen = 0while True:curr_char = self.state.memory.load(str_addr + strlen, 1)curr_val = self.state.solver.eval(curr_char)if curr_val == 0:breakstrlen += 1return strlen# 使用自定义实现
proj.hook_symbol('strlen', CustomStrlen())

2. 条件替换

根据不同条件使用不同的替换实现:

def conditional_hook(state):# 根据状态决定是否替换if state.solver.eval(state.regs.rax) > 0x1000:return angr.SIM_PROCEDURES['libc']['malloc']()return Noneproj.hook_symbol('malloc', conditional_hook)

常见问题与解决方案详解

后面这些解决方案由AI生成

1. 找不到合适的替换函数

问题表现
  • 在 Angr 的标准库中找不到目标函数的实现
  • 现有的替换函数不能完全满足分析需求
  • 需要处理特殊的或非标准的库函数
解决方案
1.1 源码分析法

首先查看 Angr 源码中类似功能的实现:

# 示例:查找字符串比较相关的函数实现
# 路径:angr/procedures/libc/strcmp.pyclass strcmp(angr.SimProcedure):def run(self, a_addr, b_addr):# 实现细节pass# 如果需要实现类似的函数,可以参考这个模板
1.2 自定义实现示例
# 自定义一个复杂的字符串处理函数
class CustomStrProcess(angr.SimProcedure):def run(self, str_addr, len_param):# 1. 参数处理strlen = self.state.solver.eval(len_param)if strlen > 1000:  # 添加合理的限制strlen = 1000# 2. 内存读取string = self.state.memory.load(str_addr, strlen)# 3. 实现特定的处理逻辑processed = self.process_string(string)# 4. 处理返回值return processeddef process_string(self, string):# 实现具体的处理逻辑pass# 使用自定义函数替换
proj.hook_symbol('target_function', CustomStrProcess())
1.3 使用近似替换

如果无法完全匹配原函数功能,可以使用功能相近的替换:

# 示例:用 strncmp 替换 strcmp
proj.hook_symbol('strcmp', angr.SIM_PROCEDURES['libc']['strncmp'](length=100))

2. 替换后行为异常

问题表现
  • 程序执行路径不符合预期
  • 符号执行过程中出现异常
  • 分析结果不准确
解决方案
2.1 函数签名检查
# 正确的函数签名示例
class CorrectMemcpy(angr.SimProcedure):def run(self, dest_addr, src_addr, length):# 确保参数类型正确if not isinstance(length, claripy.ast.Base):length = self.state.solver.BVV(length, self.state.arch.bits)# 实现内存复制逻辑return dest_addr# 使用方法
proj.hook_symbol('memcpy', CorrectMemcpy())
2.2 约束条件调整
def add_constraints(state):# 添加基本约束buff_addr = state.regs.rdi  # 假设缓冲区地址在 rdi 寄存器# 限制缓冲区大小state.add_constraints(state.mem[buff_addr].uint32_t != 0)state.add_constraints(state.mem[buff_addr].uint32_t < 1024)# 限制字符范围for i in range(32):curr_byte = state.memory.load(buff_addr + i, 1)state.add_constraints(curr_byte >= 0x20)state.add_constraints(curr_byte <= 0x7e)# 在符号执行前添加约束
state = proj.factory.entry_state()
add_constraints(state)
2.3 状态空间控制
# 设置执行超时和内存限制
def explore_with_limits():proj = angr.Project('./target_binary')state = proj.factory.entry_state()# 创建模拟管理器simgr = proj.factory.simulation_manager(state)# 设置探索限制simgr.explore(find=lambda s: b"success" in s.posix.dumps(1),avoid=lambda s: b"fail" in s.posix.dumps(1),n_find=1,  # 只需要找到一个解max_active=1000,  # 限制活动状态数量timeout=300  # 设置超时(秒))

3. 性能问题

问题表现
  • 符号执行速度过慢
  • 内存消耗过大
  • 状态爆炸
解决方案
3.1 简化替换函数
# 简化版的 strlen 实现
class FastStrlen(angr.SimProcedure):def run(self, str_addr):# 设置最大搜索长度MAX_LEN = 64# 快速扫描定长for i in range(MAX_LEN):curr_char = self.state.memory.load(str_addr + i, 1)is_null = self.state.solver.is_true(curr_char == 0)if is_null:return ireturn MAX_LEN# 使用简化版本
proj.hook_symbol('strlen', FastStrlen())
3.2 深度限制
def limited_exploration():proj = angr.Project('./target_binary')state = proj.factory.entry_state()simgr = proj.factory.simulation_manager(state)# 设置探索策略simgr.use_technique(angr.exploration_techniques.LoopSeer(loops=[0x400c40, 0x400d30],  # 指定循环的地址bound=10  # 限制循环执行次数))# 限制执行深度simgr.use_technique(angr.exploration_techniques.LengthLimiter(max_length=1000  # 最大执行步数))return simgr.run()
3.3 优化约束条件
def optimize_constraints():proj = angr.Project('./target_binary')state = proj.factory.entry_state()# 1. 添加智能约束input_size = 32input_chars = [state.solver.BVS(f'c{i}', 8) for i in range(input_size)]# 2. 使用批量约束而不是单字符约束printable = state.solver.And(state.solver.And(c >= 0x20, c <= 0x7e) for c in input_chars)state.add_constraints(printable)# 3. 使用预设值减少求解空间known_prefix = b"FLAG{"for i, c in enumerate(known_prefix):state.add_constraints(input_chars[i] == c)return state

实用建议

  1. 日志与调试

很有用

# 开启详细日志
import logging
logging.getLogger('angr').setLevel(logging.DEBUG)# 添加调试点
@proj.hook(0x400c40)
def debug_hook(state):print(f"执行到地址 0x400c40")print(f"寄存器状态: {state.regs}")print(f"内存内容: {state.mem[state.regs.rsp].uint64_t.concrete}")
  1. 性能监控
import time
import resourcedef monitor_execution():start_time = time.time()start_memory = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss# 执行分析result = run_analysis()end_time = time.time()end_memory = resource.getrusage(resource.RUSAGE_SELF).ru_maxrssprint(f"执行时间: {end_time - start_time:.2f} 秒")print(f"内存使用: {(end_memory - start_memory) / 1024:.2f} MB")return result

最佳实践总结

  1. 渐进式调试

    • 先用简单的替换函数测试
    • 逐步添加复杂功能
    • 持续监控性能变化
  2. 模块化设计

    • 将复杂的替换函数拆分为小模块
    • 便于测试和维护
    • 提高代码复用性
  3. 错误处理

    • 添加适当的错误处理机制
    • 设置合理的超时和限制
    • 保存中间状态便于调试

这些解决方案和最佳实践可以帮助你处理 Angr 库函数替换过程中遇到的大多数问题。在实际应用中,可能需要根据具体情况组合使用多种方案。

总结

库函数替换是 Angr 符号执行中的重要机制,掌握它能够帮助我们更好地控制程序分析过程。本文详细介绍了:

  1. 库函数替换的基本概念
  2. 如何查找和使用支持的库函数
  3. 常用替换函数的详细说明
  4. 实战案例演示
  5. 高级使用技巧
  6. 常见问题的解决方案

希望这篇文章能够帮助读者更好地理解和使用 Angr 的库函数替换功能。

本账号所有文章均为原创,欢迎转载,请注明文章出处:https://shandianchengzi.blog.csdn.net/article/details/144883082。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/501619.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【74HC192减法24/20/72进制】2022-5-17

缘由用74ls192设计一个72进制的减法计数器&#xff0c;需要有逻辑电路图-硬件开发-CSDN问答

Fastapi项目通过Jenkins2.4.91自动化构建部署到Nginx1.20进行访问详细方法(完全自动化部署亲测可用)

这篇技术文章需要结合我写的前两篇文章来一起看Gitlab17.7Jenkins2.4.91实现Fastapi/Django项目持续发布版本详细操作(亲测可用) 和 Pycharm2024.3Gitlab.17.7本地化部署和自动提交代码使用方法&#xff08;亲测可用&#xff09;&#xff0c;总体来说是三部曲。这篇文章详细解读…

iOS 11 中的 HEIF 图像格式 - 您需要了解的内容

HEIF&#xff0c;也称为高效图像格式&#xff0c;是iOS 11 之后发布的新图像格式&#xff0c;以能够在不压缩图像质量的情况下以较小尺寸保存照片而闻名。换句话说&#xff0c;HEIF 图像格式可以具有相同或更好的照片质量&#xff0c;同时比 JPEG、PNG、GIF、TIFF 占用更少的设…

DATACOM-DHCP-复习-实验

DHCP 概述工作原理DHCP分配机制 配置配置基于全局地址池的DHCP服务器配置DHCP Relay中继验证 实验配置DHCP中继 参考 概述 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于集中对用户IP地址进行动态管理和…

深入浅出 Beam Search:自然语言处理中的高效搜索利器

Beam Search 技术详解 搜索系列相关文章&#xff08;置顶&#xff09; 1.原始信息再加工&#xff1a;一文读懂倒排索引 2.慧眼识词&#xff1a;解析TF-IDF工作原理 3.超越TF-IDF&#xff1a;信息检索之BM25 4.深入浅出 Beam Search&#xff1a;自然语言处理中的高效搜索利器 1…

二、CSS基础

一、选择器(1) 大白话&#xff1a;我们人为认为的解析方式是&#xff0c;从左往右查找&#xff0c;对于浏览器来说&#xff0c;是从右往左查找&#xff0c;解析速度更高。 注&#xff1a; 伪类选择器 - 作用于实际存在的元素&#xff0c;用于描述元素的某种特定状态或关系&…

从摩托罗拉手机打印短信的简单方法

昨天我试图从摩托罗拉智能手机上打印短信&#xff0c;但当我通过USB将手机连接到电脑时&#xff0c;我在电脑上找不到它们。由于我的手机内存已达到限制&#xff0c;并且我想保留短信的纸质版本&#xff0c;您能帮我将短信从摩托罗拉手机导出到计算机吗&#xff1f; 如您所知&…

Linux终端输入删除键backspace显示^H,输入上下左右键显示^A^B^C^D原理以及详细解决办法!

当我们装完Linux系统之后,我们可能会碰到按下删除键后出现^H这种情况。 同样,输入上下左右键显示^A^B^C^D这种情况。 这是为什么呢? 别急,后面我会说具体解决办法,先来看看这是为什么? 一、终端程序架构 首先,我们需要了解终端程序架构。 终端程序架构分为三层,分别…

ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础

文章目录 简介为什么需要I2S&#xff1f;关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频&#xff1f;位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载…

JAVA:利用 Redis 实现每周热评的技术指南

1、简述 在现代应用中&#xff0c;尤其是社交媒体和内容平台&#xff0c;展示热门评论是常见的功能。我们可以通过 Redis 的高性能和丰富的数据结构&#xff0c;轻松实现每周热评功能。本文将详细介绍如何利用 Redis 实现每周热评&#xff0c;并列出完整的实现代码。 2、需求分…

vscode代码AI插件Continue 安装与使用

“Continue” 是一款强大的插件&#xff0c;它主要用于在开发过程中提供智能的代码延续功能。例如&#xff0c;当你在编写代码并且需要进行下一步操作或者完成一个代码块时&#xff0c;它能够根据代码的上下文、语法规则以及相关的库和框架知识&#xff0c;为你提供可能的代码续…

kafka开机自启失败问题处理

前言&#xff1a;在当今大数据处理领域&#xff0c;Kafka 作为一款高性能、分布式的消息队列系统&#xff0c;发挥着举足轻重的作用。无论是海量数据的实时传输&#xff0c;还是复杂系统间的解耦通信&#xff0c;Kafka 都能轻松应对。然而&#xff0c;在实际部署和运维 Kafka 的…

Linux Red Hat 7.9 Server安装GitLab

1、关闭防火墙 执行 systemctl disable firewalld 查看服务器状态 systemctl status firewalld 2、禁用selinux vi /etc/selinux/config 将SELINUX 的值改为 disabled 3、安装policycoreutils-python 执行 yum install policycoreutils-python 4、下载gitlab wget --co…

PostgreSQL对称between比较运算

本文介绍PostgreSQL对称between比较功能&#xff1a;between symmetric&#xff0c;在动态拼接SQL时利用它可以简化判断。PostgreSQL 9.4 及以上版本支持BETWEEN SYMMETRIC操作符&#xff0c;MySQL、Oracle、MsSQL没有对应功能。 between 比较 PostgreSQL的between结构允许你对…

[CTF/网络安全] 攻防世界 simple_php 解题详析

题目描述&#xff1a;小宁听说php是最好的语言,于是她简单学习之后写了几行php代码。 代码解读 $a$_GET[a]; 从HTTP GET请求参数中获取一个名为a的变量&#xff0c;并将其赋值给变量a。符号用于禁止错误输出&#xff0c;如果不存在参数a则会将变量a设置为NULL。 $b$_GET[b];…

日志聚类算法 Drain 的实践与改良

在现实场景中&#xff0c;业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时&#xff0c;平铺的日志列表会让我们目不暇接&#xff0c;难以快速聚焦找到重要的日志条目。 在观测云中&#xff0c;我们在日志页面提供了聚类分析功能&#xff0c;可以…

RabbitMQ基础篇之Java客户端快速入门

文章目录 需求 项目设置与依赖管理 配置RabbitMQ的连接信息创建队列与消息发送创建消费者&#xff08;消息接收&#xff09;环境准备与操作 需求 利用控制台创建队列 simple.queue在 publisher 服务中&#xff0c;利用 SpringAMQP 直接向 simple.queue 发送消息在 consumer 服…

在虚幻引擎4(UE4)中使用蓝图的详细教程

在虚幻引擎4&#xff08;UE4&#xff09;中使用蓝图的详细教程 虚幻引擎4&#xff08;Unreal Engine 4&#xff0c;简称UE4&#xff09;是一款功能强大的游戏引擎&#xff0c;广泛应用于游戏开发、虚拟现实、建筑可视化等领域。UE4 提供了一个强大的可视化脚本工具——蓝图&am…

初学STM32 ---高级定时器互补输出带死区控制

互补输出&#xff0c;还带死区控制&#xff0c;什么意思&#xff1f; 带死区控制的互补输出应用之H桥 捕获/比较通道的输出部分&#xff08;通道1至3&#xff09; 死区时间计算 举个栗子&#xff08;F1为例&#xff09;&#xff1a;DTG[7:0]250&#xff0c;250即二进制&#x…

MarkDown怎么转pdf;Mark Text怎么使用;

MarkDown怎么转pdf 目录 MarkDown怎么转pdf先用CSDN进行编辑,能双向看版式;标题最后直接导出pdfMark Text怎么使用一、界面介绍二、基本操作三、视图模式四、其他功能先用CSDN进行编辑,能双向看版式; 标题最后直接导出pdf Mark Text怎么使用 Mark Text是一款简洁的开源Mar…