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 基本流程
- 创建 TritonContext 对象
- 设置架构类型
- 封装指令并执行
- 分析指令信息
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 关键步骤
- 标记污点源
- 执行指令时进行污点传播
- 分析污点数据流向
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 关键步骤
- 设置符号量
- 执行指令时维护符号传播
- 在关键分支设置约束条件
- 求解满足约束的输入
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. 实用技巧
-
初始化执行环境:
- 使用
concretizeAllMemory()和concretizeAllRegister()重置状态 - 设置合理的栈和寄存器初始值
- 使用
-
加载二进制文件:
- 使用 lief 模块解析 ELF 文件
- 将各段内容加载到 Triton 内存中
-
调试技巧:
- 使用
print(inst)查看指令详细信息 - 检查
isMemoryRead()和isMemoryWrite()监控内存访问 - 使用
getOperands()分析指令操作数
- 使用
8. 参考资源
- Triton GitHub 仓库
- 官方示例代码
- LIEF 二进制解析工具