深入浅出angr(五)
字数 1037 2025-08-06 00:25:08

深入浅出angr(五) - 跨平台符号执行实战指南

前言

angr作为符号执行框架,其优势在于无需实际运行目标程序即可进行分析。本教程将详细介绍如何利用angr处理不同平台下的二进制程序,包括ARM程序、Windows DLL和Windows驱动等场景。

一、ARM程序分析实战

android_arm_license_validation为例,展示如何处理ARM架构程序。

关键步骤

  1. 初始状态设置

    • 从IDA分析确定关键函数(如sub_1760
    • 创建空白状态:state = b.factory.blank_state(addr=0x401760)
  2. 参数设置

    concrete_addr = 0xfff00000
    code = claripy.BVS('code', 10*8)
    state.memory.store(concrete_addr, code, endness='Iend_BE')
    
    • 注意ARM程序是大端对齐(Iend_BE)
  3. ARM调用约定

    • 设置r0寄存器为输入地址:state.regs.r0 = concrete_addr

二、Windows DLL分析实战

mma_howtouse为例,展示如何处理Windows DLL。

关键步骤

  1. 加载选项

    p = angr.Project('howtouse.dll', 
                    load_options={'main_opts': {'base_addr': 0x10000000}})
    
    • 注意DLL基址通常为0x10000000而非0x400000
  2. Callable方法

    howtouse = p.factory.callable(0x10001130)
    
    • 将DLL函数转换为Python可调用对象
  3. 结果提取

    getch = lambda i: chr(claripy.backends.concrete.convert(howtouse(i)).value)
    flag = ''.join(getch(i) for i in range(45))
    

三、Windows驱动分析实战

flareon2015_10为例,展示如何处理大型Windows驱动。

关键步骤

  1. 识别关键函数

    • 通过IDA分析确定sub_29cd20sub_2D2E0是关键函数
    • 发现TEA解密函数sub_110F0
  2. 手动解密实现

    void decrypt(uint32_t* v, uint32_t* k) {
        uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;
        uint32_t delta=0x61C88647;
        uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
    
        for(i=0; i<32; i++) {
            v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
            v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
            sum += delta;
        }
        v[0]=v0; v[1]=v1;
    }
    
  3. angr Hook方法

    def before_tea_decrypt(state):
        all_bytes = bytes([0x56,0x7f,0xdc,0xfa,...]) # 40字节数据
        state.memory.store(ARRAY_ADDRESS, all_bytes)
    
    p.hook(0xadc31, before_tea_decrypt, length=0)
    
  4. Callable调用

    prototype = SimTypeFunction((SimTypeInt(False),), SimTypeInt(False))
    proc_big_68 = p.factory.callable(0x2D2E0, 
                                    cc=p.factory.cc(func_ty=prototype),
                                    toc=None, 
                                    concrete_only=True)
    proc_big_68.perform_call(0)
    state = proc_big_68.result_state
    flag = state.solver.eval(state.memory.load(ARRAY_ADDRESS, 40), cast_to=bytes)
    

四、跨平台分析关键点总结

  1. 调用约定理解

    • ARM使用寄存器传参(r0-r3)
    • Windows使用stdcall/cdecl等约定
  2. 内存对齐方式

    • ARM可能是大端(Iend_BE)或小端
    • x86是小端
  3. 入口点选择

    • 不需要从程序真正入口开始
    • 选择关键函数作为起点
  4. 状态初始化

    • blank_state用于创建空白状态
    • callable用于函数级符号执行
  5. Hook技巧

    • 长度设为0实现"插桩"效果
    • 可修改内存或寄存器状态

五、实用技巧

  1. IDA交叉引用

    • 用于追踪数据流和函数调用关系
  2. claripy使用

    • BVS创建符号变量
    • BVV创建具体值
  3. 结果提取

    state.solver.eval(..., cast_to=bytes)
    
  4. 大型二进制处理

    • 聚焦关键函数
    • 避免全程序符号执行

通过掌握这些技术,你可以使用angr高效分析各种平台的二进制程序,无需搭建复杂的动态调试环境。

深入浅出angr(五) - 跨平台符号执行实战指南 前言 angr作为符号执行框架,其优势在于无需实际运行目标程序即可进行分析。本教程将详细介绍如何利用angr处理不同平台下的二进制程序,包括ARM程序、Windows DLL和Windows驱动等场景。 一、ARM程序分析实战 以 android_arm_license_validation 为例,展示如何处理ARM架构程序。 关键步骤 初始状态设置 : 从IDA分析确定关键函数(如 sub_1760 ) 创建空白状态: state = b.factory.blank_state(addr=0x401760) 参数设置 : 注意ARM程序是大端对齐(Iend_ BE) ARM调用约定 : 设置r0寄存器为输入地址: state.regs.r0 = concrete_addr 二、Windows DLL分析实战 以 mma_howtouse 为例,展示如何处理Windows DLL。 关键步骤 加载选项 : 注意DLL基址通常为0x10000000而非0x400000 Callable方法 : 将DLL函数转换为Python可调用对象 结果提取 : 三、Windows驱动分析实战 以 flareon2015_10 为例,展示如何处理大型Windows驱动。 关键步骤 识别关键函数 : 通过IDA分析确定 sub_29cd20 和 sub_2D2E0 是关键函数 发现TEA解密函数 sub_110F0 手动解密实现 : angr Hook方法 : Callable调用 : 四、跨平台分析关键点总结 调用约定理解 : ARM使用寄存器传参(r0-r3) Windows使用stdcall/cdecl等约定 内存对齐方式 : ARM可能是大端(Iend_ BE)或小端 x86是小端 入口点选择 : 不需要从程序真正入口开始 选择关键函数作为起点 状态初始化 : blank_state 用于创建空白状态 callable 用于函数级符号执行 Hook技巧 : 长度设为0实现"插桩"效果 可修改内存或寄存器状态 五、实用技巧 IDA交叉引用 : 用于追踪数据流和函数调用关系 claripy使用 : BVS 创建符号变量 BVV 创建具体值 结果提取 : 大型二进制处理 : 聚焦关键函数 避免全程序符号执行 通过掌握这些技术,你可以使用angr高效分析各种平台的二进制程序,无需搭建复杂的动态调试环境。