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