深入浅出angr(二)
字数 747 2025-08-06 08:35:32

深入浅出angr(二) - 输入输出与条件约束

1. 命令行输入处理

1.1 基本方法

在angr中处理命令行输入需要使用claripy模块创建符号变量:

import angr
import claripy

# 创建符号变量
argv1 = claripy.BVS("argv1", 100*8)  # 100字节的符号变量
initial_state = p.factory.entry_state(args=["./ais3_crackme", argv1])

1.2 获取执行结果

找到正确路径后,可以通过solver.eval()获取符号变量的具体值:

found = sm.found[0]
solution = found.solver.eval(argv1, cast_to=bytes)
solution = solution[:solution.find(b"\x00")]  # 截取到第一个null字节

2. 标准输入处理

2.1 构造输入变量

对于标准输入(stdin),可以构造字符数组:

flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(28)]  # 28个字节
flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')])  # 添加换行符

2.2 初始化状态

对于C++程序,需要使用full_init_state并启用unicorn引擎:

st = p.factory.full_init_state(
    args=['./wyvern'],
    add_options=angr.options.unicorn,
    stdin=flag,
)

2.3 添加约束条件

为提高效率,可以添加输入约束:

for k in flag_chars:
    st.solver.add(k != 0)
    st.solver.add(k != 10)  # 排除换行符

3. 执行管理

3.1 三种执行方式

  1. step(): 每次运行一个基本块
  2. run(): 运行所有基本块,返回deadended状态
  3. explore(): 根据find/avoid条件执行

3.2 从deadended状态提取结果

for pp in sm.deadended:
    out = pp.posix.dumps(1)  # 获取stdout
    if b'flag{' in out:
        return out[out.find(b"flag{"):]

4. 高级条件约束

4.1 内存约束

可以对内存内容添加约束:

flag_addr = found.regs.rdi
found.add_constraints(
    found.memory.load(flag_addr, 5) == int(binascii.hexlify(b"ASIS{"), 16)
)

4.2 复杂约束示例

flag = found.memory.load(flag_addr, 40)
for i in range(5, 5+32):
    # 约束字符在0-9或a-f范围内
    cond_0 = flag.get_byte(i) >= ord('0')
    cond_1 = flag.get_byte(i) <= ord('9')
    cond_2 = flag.get_byte(i) >= ord('a')
    cond_3 = flag.get_byte(i) <= ord('f')
    cond_4 = found.solver.And(cond_0, cond_1)
    cond_5 = found.solver.And(cond_2, cond_3)
    found.add_constraints(found.solver.Or(cond_4, cond_5))
    
# 约束最后一个字符为}
found.add_constraints(flag.get_byte(32+5) == ord('}'))

5. 完整示例

5.1 命令行输入示例

#!/usr/bin/env python
import angr
import claripy

def main():
    project = angr.Project("./ais3_crackme")
    argv1 = claripy.BVS("argv1", 100*8)
    initial_state = project.factory.entry_state(args=["./crackme1", argv1])
    sm = project.factory.simulation_manager(initial_state)
    sm.explore(find=0x400602)  # 正确分支地址
    found = sm.found[0]
    solution = found.solver.eval(argv1, cast_to=bytes)
    solution = solution[:solution.find(b"\x00")]
    print(solution)
    return solution

if __name__ == '__main__':
    print(repr(main()))

5.2 标准输入示例

import angr
import claripy

def solve():
    p = angr.Project("./wyvern")
    flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(28)]
    flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')])
    
    st = p.factory.full_init_state(
        args=['./wyvern'],
        add_options=angr.options.unicorn,
        stdin=flag,
    )
    
    for k in flag_chars:
        st.solver.add(k != 0)
        st.solver.add(k != 10)
    
    sm = p.factory.simulation_manager(st)
    sm.run()
    
    for pp in sm.deadended:
        out = pp.posix.dumps(1)
        if b'flag{' in out:
            return out[out.find(b"flag{"):]

6. 关键点总结

  1. 符号变量创建:使用claripy.BVS()创建符号变量,BVV()创建具体值
  2. 状态初始化entry_state用于命令行参数,full_init_state用于复杂程序
  3. 约束添加:通过solver.add()添加约束条件提高效率
  4. 结果提取:使用solver.eval()将符号值转换为具体值
  5. 执行控制:根据需求选择step()run()explore()
  6. 内存操作:可以通过memory.load()memory.store()操作内存

通过掌握这些技术,可以有效地使用angr进行二进制分析,解决各种逆向工程问题。

深入浅出angr(二) - 输入输出与条件约束 1. 命令行输入处理 1.1 基本方法 在angr中处理命令行输入需要使用 claripy 模块创建符号变量: 1.2 获取执行结果 找到正确路径后,可以通过 solver.eval() 获取符号变量的具体值: 2. 标准输入处理 2.1 构造输入变量 对于标准输入(stdin),可以构造字符数组: 2.2 初始化状态 对于C++程序,需要使用 full_init_state 并启用unicorn引擎: 2.3 添加约束条件 为提高效率,可以添加输入约束: 3. 执行管理 3.1 三种执行方式 step() : 每次运行一个基本块 run() : 运行所有基本块,返回deadended状态 explore() : 根据find/avoid条件执行 3.2 从deadended状态提取结果 4. 高级条件约束 4.1 内存约束 可以对内存内容添加约束: 4.2 复杂约束示例 5. 完整示例 5.1 命令行输入示例 5.2 标准输入示例 6. 关键点总结 符号变量创建 :使用 claripy.BVS() 创建符号变量, BVV() 创建具体值 状态初始化 : entry_state 用于命令行参数, full_init_state 用于复杂程序 约束添加 :通过 solver.add() 添加约束条件提高效率 结果提取 :使用 solver.eval() 将符号值转换为具体值 执行控制 :根据需求选择 step() 、 run() 或 explore() 内存操作 :可以通过 memory.load() 和 memory.store() 操作内存 通过掌握这些技术,可以有效地使用angr进行二进制分析,解决各种逆向工程问题。