动态二进制插桩工具Pin和pintools
Pin简介
Intel官方文档 Pin,概述,下载,手册等都有
Pin是intel开发的一个动态二进制插桩工具,提供了丰富的API,支持windows、linux、macos,适用于 IA-32、x86-64 和 MIC 指令集架构。
动态二进制插桩(Dynamic Binary Instrumentation,DBI)的含义:不需要源代码,可以在二进制可执行文件文件的任意位置插入任意的代码 (C/C++ 编写),可以将代码动态地添加到正在执行地可执行文件中。目前的DBI平台有Pin、DynamoRIO、Valgrind等。
基于Pin提供的API开发(c,c++,asm)的工具为pintools。Pin最初是计算机体系结构分析工具,但其灵活的API和活跃的社区(称为“ Pinheads ”)创建了一组用于安全、仿真和并行程序分析的多样化工具。
Pin的功能:可以用自己的函数替换程序中的函数,并且在自己的函数中调用被替换的函数;可以在指令中插入对检测函数的调用,使得在执行指令时执行检测函数,同时可以给检测函数传递参数(寄存器值、指令读写的内存地址、寄存器上下文);可以随时attach和detach进程,即可以自定义在程序中需要插桩和检测的部分;可以追踪函数调用以及syscall,检测/改变参数;可以配合调试器(如gdb)使用,实现调试器的一些拓展功能;跟踪应用程序子线程;拦截signal信号;检测进程树等。
Pintool使用
先看readme,介绍了pintools的编译和基本使用
readme演示的是opcodemix,它可以用来分析程序包含的不同指令组合的数目,比如可以比较两款编译器编译生成的文件的指令组合的差异
1 |
|
编译ManualExamples下的所有Pintool(64位),编译生成的文件会放在obj-intel64目录中
1 |
|
使用编译好的工具,我们需要.so文件-t指明要使用的pintool,–后面是要插桩运行的程序
1 |
|
这里使用的是inscount0,可以统计运行的指令数量,结果保存在运行时所在目录下的inscount.out文件,inscount0、incount1、inscount2的区别在于后者对运行效率进行了优化。
Pintool架构
windows和linux下Pin的大致架构都是如下
- 供 pintool 调用的API库。Linux下是instrumentation api 库,windows中是PIN.LIB;
- VM:即 virtual machine,它的功能主要是插桩并执行程序,过程类似于即时编译,只是编译变成了插桩。大致流程是:先对部分代码进行插桩,放到code cache中运行,运行时需要跳转到未插桩的代码时再对相应代码进行插桩并放入code cache。linux中包含了 emulation unit 用来处理系统调用,JIT 编译器负责编译和插桩,每次取一个 trace 编译后送到 code cache 中;windows原理相同,主要功能集中在PINVM.DLL,执行过程大概是启动pin.exe以debugger的模式,附加要分析程序的进程 -> 注入pinvm.dll->注入pintool的dll->开始运行。
- code cache:用来存储插桩后的代码,真正执行的是 code cache 中的代码,原目标插桩文件中的代码不会执行。
linux下的架构
windows下的架构
编写自己的Pintools
阅读不同版本Pin对应的用户手册,其中有详细的API及示例,如Pin 3.28 User Guide
[V4ler1an的博客],主要是官方文档的相关内容的整理总结,博主是看雪二进制漏洞板块小版主。
intel sde
sde基于pin和xed,sde在pin插桩分析的基础上多了仿真的功能,可以在特定指令集架构上运行给定程序并捕获各种性能详细信息,可以供开发人员提前熟悉和探索即将推出的新指令集,为在软件中使用新指令集做准备。
Intel X86 Encoder Decoder (XED) 是一个软件库,用于编码和解码 X86(IA32 和 Intel64)指令。解码器采用 1-15 字节的序列以及机器模式信息,并生成描述操作码、操作数和标志的数据结构。编码器采用类似的数据结构并生成 1 到 15 个字节的序列。反汇编本质上是对数据结构的打印。
即XED可以对x86/64代码进行反汇编以及将汇编转化为机器码,可执行程序xed可以反汇编PE和ELF可执行文件。
sde基本使用
中括号表示可选参数
1 |
|
用sde运行cmd或shell可以使所有在cmd/shell中运行的程序都在sde的控制之下,sde可以收集并分析所有该命令行中的内容。
例如:
1 |
|
1 |
|
Pin in CTF
因为Pin能够直接对可执行程序动态插桩进行信息收集,所以求解部分ctf题有奇效。
主要用于程序复杂(如复杂的vm逆向以及混淆题)但是对flag(input)的检测是逐位的情况下,每一位的对错都会导致执行流的改变,执行时间或执行指令数量相差巨大,这样就能进行侧信道逐位爆破。
[ctf-wiki]intel pin上有两道例题
2023香山杯nesting
一道vm题,但这里可以不用ida分析
程序运行后会让你输入flag并检测flag是否正确
1 |
|
用sde来统计程序运行到的指令数量,结果会在命令行以ICOUNT: 3421916的形式输出,这也方便爆破脚本的编写
1 |
|
可以发现每多输入一位,总指令数都会增加20万左右
flag的前4位必定是”flag”,分别输入”1111”,”f111”,”fl11”,”fla1”,”flag”可以发现在位数相同的情况下,flag每正确一位总指令数会增加55000左右,说明flag是逐位check的,并且不同结果的执行流长度相差较大,可以通过这一点来爆破flag
爆破脚本,来自Re神
1 |
|