Triton 学习
字数 921 2025-08-05 08:16:32

Triton 动态二进制分析框架教学文档

1. Triton 简介

Triton 是一款强大的动态二进制分析框架,主要功能包括:

  • 符号执行
  • 污点分析
  • 提供 pintools 的 Python 接口
  • 支持架构:x86、x64、AArch64

2. 安装 Triton

2.1 安装依赖

sudo apt-get install libz3-dev libcapstone-dev libboost-dev libopenmpi-dev

2.2 编译安装

git clone https://github.com/JonathanSalwan/Triton.git
cd Triton
mkdir build
cd build
cmake ..
sudo make -j install

2.3 常见安装问题解决

缺少 OpenMP 库

在 CMakeLists.txt 中添加:

set(CMAKE_C_FLAGS "-fopenmp")
set(CMAKE_CXX_FLAGS "-fopenmp")

Z3 版本过旧

使用新版 Z3 编译:

cmake .. -DZ3_INCLUDE_DIRS="/path/to/z3/include" -DZ3_LIBRARIES="/path/to/z3/bin/libz3.a"

3. Triton 基础使用

3.1 基本流程

  1. 创建 TritonContext 对象
  2. 设置架构类型
  3. 封装指令并执行
  4. 分析指令信息

3.2 示例代码

from triton import TritonContext, ARCH, Instruction, OPERAND

# 初始化
Triton = TritonContext()
Triton.setArchitecture(ARCH.X86_64)

# 指令列表
code = [
    (0x40000, b"\x40\xf6\xee"),  # imul sil
    # 更多指令...
]

for (addr, opcode) in code:
    inst = Instruction()
    inst.setOpcode(opcode)
    inst.setAddress(addr)
    Triton.processing(inst)  # 执行指令
    
    # 打印指令信息
    print(inst)
    print('Is memory read:', inst.isMemoryRead())
    print('Is memory write:', inst.isMemoryWrite())
    
    for op in inst.getOperands():
        print('Operand:', op)
        if op.getType() == OPERAND.MEM:
            print(' - segment:', op.getSegmentRegister())
            print(' - base:', op.getBaseRegister())
            print(' - index:', op.getIndexRegister())
            print(' - scale:', op.getScale())
            print(' - disp:', op.getDisplacement())

4. 模拟执行

4.1 关键 API

  • setConcreteRegisterValue(): 设置寄存器值
  • setConcreteMemoryValue(): 设置内存值
  • getConcreteMemoryAreaValue(): 获取内存数据
  • getConcreteRegisterValue(): 获取寄存器值

4.2 示例:爆破 CMU bomb 题目 phase_4

def crack():
    i = 1
    Triton.setConcreteMemoryValue(MemoryAccess(EBP_ADDR - 0x14, CPUSIZE.DWORD), i)
    pc = 0x8048CED
    
    while pc:
        opcode = Triton.getConcreteMemoryAreaValue(pc, 16)
        instruction = Instruction()
        instruction.setOpcode(opcode)
        instruction.setAddress(pc)
        Triton.processing(instruction)
        
        if instruction.getAddress() == 0x08048D01:
            print("solve! answer: %d" %(i))
            break
            
        if instruction.getAddress() == 0x8048D07:
            pc = 0x8048CED
            i += 1
            init_machine()
            Triton.setConcreteMemoryValue(MemoryAccess(EBP_ADDR - 0x14, CPUSIZE.DWORD), i)
            continue
            
        pc = Triton.getConcreteRegisterValue(Triton.registers.eip)

5. 污点分析

5.1 关键步骤

  1. 标记污点源
  2. 执行指令时进行污点传播
  3. 分析污点数据流向

5.2 示例:监控输入字符串访问

# 设置输入字符串
input = "elite\x00"
ctx.setConcreteMemoryAreaValue(INPUT_ADDR, input)
ctx.taintMemory(MemoryAccess(INPUT_ADDR, 8))  # 标记污点源

while pc != 0x4005B1:
    inst = Instruction()
    opcode = ctx.getConcreteMemoryAreaValue(pc, 16)
    inst.setOpcode(opcode)
    inst.setAddress(pc)
    ctx.processing(inst)
    
    if inst.isTainted():  # 检查是否涉及污点数据
        if inst.isMemoryRead():
            for op in inst.getOperands():
                if op.getType() == OPERAND.MEM:
                    print("read:0x{:08x}, size:{}".format(op.getAddress(), op.getSize()))

6. 符号执行

6.1 关键步骤

  1. 设置符号量
  2. 执行指令时维护符号传播
  3. 在关键分支设置约束条件
  4. 求解满足约束的输入

6.2 示例:求解 crackme_xor

# 将输入转换为符号量
for index in range(5):
    ctx.setConcreteMemoryValue(MemoryAccess(INPUT_ADDR + index, CPUSIZE.BYTE), ord('b'))
    ctx.convertMemoryToSymbolicVariable(MemoryAccess(INPUT_ADDR + index, CPUSIZE.BYTE))

while pc:
    inst = Instruction()
    opcode = ctx.getConcreteMemoryAreaValue(pc, 16)
    inst.setOpcode(opcode)
    inst.setAddress(pc)
    ctx.processing(inst)
    
    if inst.getAddress() == 0x400597:  # 关键分支
        zf = ctx.getRegisterAst(ctx.registers.zf)
        cstr = ast.land([ctx.getPathConstraintsAst(), zf == 1])  # 设置约束
        
        # 求解并具体化
        model = ctx.getModel(cstr)
        for k, v in list(model.items()):
            value = v.getValue()
            ctx.setConcreteVariableValue(ctx.getSymbolicVariableFromId(k), value)
    
    if inst.getAddress() == 0x4005B1:  # 成功分支
        model = ctx.getModel(ctx.getPathConstraintsAst())
        answer = ""
        for k, v in list(model.items()):
            value = v.getValue()
            answer += chr(value)
        print("answer: {}".format(answer))
        break

7. 实用技巧

  1. 初始化执行环境

    • 使用 concretizeAllMemory()concretizeAllRegister() 重置状态
    • 设置合理的栈和寄存器初始值
  2. 加载二进制文件

    • 使用 lief 模块解析 ELF 文件
    • 将各段内容加载到 Triton 内存中
  3. 调试技巧

    • 使用 print(inst) 查看指令详细信息
    • 检查 isMemoryRead()isMemoryWrite() 监控内存访问
    • 使用 getOperands() 分析指令操作数

8. 参考资源

Triton 动态二进制分析框架教学文档 1. Triton 简介 Triton 是一款强大的动态二进制分析框架,主要功能包括: 符号执行 污点分析 提供 pintools 的 Python 接口 支持架构:x86、x64、AArch64 2. 安装 Triton 2.1 安装依赖 2.2 编译安装 2.3 常见安装问题解决 缺少 OpenMP 库 在 CMakeLists.txt 中添加: Z3 版本过旧 使用新版 Z3 编译: 3. Triton 基础使用 3.1 基本流程 创建 TritonContext 对象 设置架构类型 封装指令并执行 分析指令信息 3.2 示例代码 4. 模拟执行 4.1 关键 API setConcreteRegisterValue() : 设置寄存器值 setConcreteMemoryValue() : 设置内存值 getConcreteMemoryAreaValue() : 获取内存数据 getConcreteRegisterValue() : 获取寄存器值 4.2 示例:爆破 CMU bomb 题目 phase_ 4 5. 污点分析 5.1 关键步骤 标记污点源 执行指令时进行污点传播 分析污点数据流向 5.2 示例:监控输入字符串访问 6. 符号执行 6.1 关键步骤 设置符号量 执行指令时维护符号传播 在关键分支设置约束条件 求解满足约束的输入 6.2 示例:求解 crackme_ xor 7. 实用技巧 初始化执行环境 : 使用 concretizeAllMemory() 和 concretizeAllRegister() 重置状态 设置合理的栈和寄存器初始值 加载二进制文件 : 使用 lief 模块解析 ELF 文件 将各段内容加载到 Triton 内存中 调试技巧 : 使用 print(inst) 查看指令详细信息 检查 isMemoryRead() 和 isMemoryWrite() 监控内存访问 使用 getOperands() 分析指令操作数 8. 参考资源 Triton GitHub 仓库 官方示例代码 LIEF 二进制解析工具