二进制插桩:静态插桩和动态intel pin插桩

news2025/1/19 11:27:54

目前有两类插桩平台:静态插桩(SBI)和动态插桩(DBI)

  • SBI使用二进制重写方法永久修改磁盘上的二进制文件;
  • DBI不会修改磁盘上的二进制程序,而是监视二进制程序的执行状态,并在其运行时将新指令插入指令流中

一、DBI动态intel pin插桩 

​​​​​​​​​​​​​​​​​​​​​https://www.cnblogs.com/level5uiharu/p/16963907.html​​​​​​​

intel Pin简要介绍及示例程序-CSDN博客

Pin可以被看做一个即时JIT编译器(Just in Time)。它可以程序运行时拦截常规可执行文件的指令,并在指令执行前生成新的代码,然后去执行生成的新的代码,并在新的代码执行完成后,将控制权交给被拦截的指令。Pin不开源,Pin的DBI引擎和Pintool都运行于用户空间,因此只能插桩用户空间进程。

intel Pin的官方介绍Pin: Pin 3.21 User Guide (intel.com)

intel Pin的API文档Pin: API Reference (intel.com)

intel Pin的下载地址Pin - A Dynamic Binary Instrumentation Tool (intel.com)

步骤:
1. 命令行选项和数据结构
Pintool可以实现特定工具的命令行选项,这些选项在Pin术语中称为开关(knob),PinAPI中包括一个专用的KNOB类,用于创建命令行选项。在下图代码中,有两个布尔选项(KNOB<bool>),分别是ProfileCalls和ProfileSyscalls,可通过将-c标志传递给Pintool来启用ProfileCalls选项,并通过传递-s标志启用ProfileSyscalls选项。
KNOB<bool> ProfileCalls(KNOB_MODE_WRITEONCE, "pintool", "c", "0", "Profile function calls");
KNOB<bool> ProfileSyscalls(KNOB_MODE_WRITEONCE, "pintool", "s", "0", "Profile syscalls");

2. 初始化pin

从main函数开始,调用的第一个Pin函数是PIN_InitSymbols,该函数表示Pin读取应用程序的符号表,接下来调用PIN_Init函数来初始化Pin

3. 注册插桩例程

Profiler需要注册3个插桩例程,其中第一个是parse_funcsyms,进行img粒度的插桩,另外两个为instrument_trace和instrument_insn,分别进行踪迹和指令粒度的插桩。

IMG_AddInstrumentFunction(parse_funcsyms, NULL);
INS_AddInstrumentFunction(instrument_insn, NULL);
TRACE_AddInstrumentFunction(instrument_trace, NULL);

4. 注册系统调用入口函数接口

Profiler使用PIN_AddSyscallEntryFunction函数注册一个名为log_syscall的函数

PIN_AddSyscallEntryFunction(log_syscall, NULL);

5. 注册fini函数

Profiler注册的最后一个回调函数是fini函数,该函数在应用程序退出时或者Pin从程序分离时被调用

6. 启动应用程序

每个Pintool初始化的最后一步都是调用了PIN_StartProgram函数来启动应用程序。

PIN_StartProgram();

7. 测试

命令行中的-c -s 用于打开函数调用和进行系统调用分析

Profiler输出关于执行指令的数量、控制转移、函数调用和系统调用的统计分析

接下来,就上述TRACE_AddInstrumentFunction插桩例程为例进行介绍,该插桩例程的第一个函数instrument_trace代表Profiler注册的踪迹粒度trace的插桩例程。以下是详细代码:

首先,instrument_trace函数使用路径的地址调用IMG_FindByAddress函数查找踪迹所属的IMG;
接下来,验证IMG是否有效且检查路径是否为主应用程序,若不是,则不插桩。因为当评测应用程序时,通常希望只计算应用程序内部的代码,而不是共享库或者动态加载器中的代码;
如果trace是有效的并且为主应用程序,那么instrument_trace循环遍历路径中的所有基本快BBL,并对每个BBL调用instrument_bb函数,该函数对BBL执行实际的插桩;
instrument_bb函数通过调用BBL_InsertCall函数对给定的BBL进行插桩
BBL_InsertCall使用分析例程来插桩基本块的Pin API函数,需接收3个必需的参数:待插桩的基本块(本例中是bb)、IPOINT_ANYWHERE)及指向待添加的分析例程的函数指针(count_bb_insns)

最终结果是,Pin用指向count_bb_insns的回调对主应用程序的实际执行的bb块进行插桩,count_bb_insns为profiler的指令计数器加上每个基本块中指令的数量。

 程序代码:

static void
instrument_trace(TRACE trace, void *v)
{
  IMG img = IMG_FindByAddress(TRACE_Address(trace));
  if(!IMG_Valid(img) || !IMG_IsMainExecutable(img)) return;
 
  for(BBL bb = TRACE_BblHead(trace); BBL_Valid(bb); bb = BBL_Next(bb)) {
    instrument_bb(bb);
  }
}
 
static void
instrument_bb(BBL bb)
{
  BBL_InsertCall(
    bb, IPOINT_ANYWHERE, (AFUNPTR)count_bb_insns,
    IARG_UINT32, BBL_NumIns(bb),
    IARG_END
  );
}

static void
count_bb_insns(UINT32 n)
{
  insn_count += n;
}

#include <stdio.h>
#include <map>
#include <string>
#include <asm-generic/unistd.h>
 
#include "pin.H"
 
KNOB<bool> ProfileCalls(KNOB_MODE_WRITEONCE, "pintool", "c", "0", "Profile function calls");
KNOB<bool> ProfileSyscalls(KNOB_MODE_WRITEONCE, "pintool", "s", "0", "Profile syscalls");
 
std::map<ADDRINT, std::map<ADDRINT, unsigned long> > cflows;
std::map<ADDRINT, std::map<ADDRINT, unsigned long> > calls;
std::map<ADDRINT, unsigned long> syscalls;
std::map<ADDRINT, std::string> funcnames;
 
unsigned long insn_count    = 0;
unsigned long cflow_count   = 0;
unsigned long call_count    = 0;
unsigned long syscall_count = 0; 
 
int
main(int argc, char *argv[])
{
  PIN_InitSymbols();
  if(PIN_Init(argc,argv)) {
    print_usage();
    return 1;
  }
 
  IMG_AddInstrumentFunction(parse_funcsyms, NULL);
  INS_AddInstrumentFunction(instrument_insn, NULL);
  TRACE_AddInstrumentFunction(instrument_trace, NULL);
  if(ProfileSyscalls.Value()) {
    PIN_AddSyscallEntryFunction(log_syscall, NULL);
  }
  PIN_AddFiniFunction(print_results, NULL);
 
  /* Never returns */
  PIN_StartProgram();
    
  return 0;
}

二、SBI二进制静态插桩

SBI对二进制程序进行反汇编,然后按需添加插桩代码并将更新的二进制程序存入磁盘。SBI平台包括PEBIL和Dyninst,都是研究工具,没有详细的文档。SBI主要挑战是,在不破坏任何现有代码和数据引用的前提下,添加插桩代码并重写二进制程序。目前有两种流行的解决方法:

1.int3方法;
2.跳板(trampoline)方法;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1239120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ Day04 this指针,友元函数,重载

this指针 概念 谁调用 this 所在的函数 ,this 就存储谁的地址 特点 1, 在当前类的非静态成员函数中调用本类非静态成员时 , 默认有 this 关键字 2, 静态成员函数 , 没有 this 指针。 示例 #include <iostream> #include <cstring> using namespace std; class S…

羊大师教你如何有效解决工作中的挑战与压力?

在现代社会&#xff0c;工作问题一直是许多人头疼的难题。无论是从工作压力到职业发展&#xff0c;工作问题不仅会影响个人的心理健康&#xff0c;还可能对整个工作团队的效率和和谐产生负面影响。因此&#xff0c;如何有效解决工作问题成为了每个职场人士都需要面对的挑战。 …

什么是Zero-shot(零次学习)

1 Zero-shot介绍 Zero-shot学习&#xff08;ZSL&#xff09;是机器学习领域的一种先进方法&#xff0c;它旨在使模型能够识别、分类或理解在训练过程中未见过的类别或概念。这种学习方法对于解决现实世界中常见的长尾分布问题至关重要&#xff0c;即对于一些罕见或未知类别的样…

vue2指令的使用和自定义指令

前言 个人认为vue的指令,对比react来说,给开发者节省了很大的学习成本。比如在react中,你想渲染一个列表,需要用Array.map的方法return<div>,而在vue中,一个简单的v-for就解决了问题。 在学习成本和入手体验上,vue的作者确实后来者居上,能让人更快的使用vue开发。不过也…

vs调试输出,不显示线程已退出

如题&#xff1a;一堆线程退出的信息&#xff0c;招人烦。 其实在vs设置里可以关闭&#xff1a; 工具-->选项-->调试-->输出窗口&#xff1a;

【Linux】权限的理解和使用

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Linux程序之可变参数选项那些事!

一、linux应用程序如何接收参数&#xff1f; 1. argc、argv Linux应用程序执行时&#xff0c;我们往往通过命令行带入参数给程序&#xff0c;比如 ls /dev/ -l 其中参数 /dev/ 、-l都是作为参数传递给命令 ls 应用程序又是如何接收这些参数的&#xff1f; 通常应用程序都…

程序的执行原理(上)

文章目录 hello world程序源文件的本质是0和1hello world文件的ASCII表示程序被其他程序翻译成不同的格式预处理阶段编译阶段汇编阶段链接阶段 为什么需要了解编译系统的工作原理&#xff1f;优化程序性能理解链接时出现的错误避免安全漏洞 运行程序参考 hello world 程序源文件…

基于ZLMediaKit的GB28181视频平台demo

GB28181 主要内容 国标的20位id是按照标准来定的&#xff0c;前8位是地域信息&#xff0c;9-10位是行业信息&#xff0c;11-13是设备类型、14是网络标识、后6位为序号 约定以SIP协议作为会话通道的使用标准&#xff0c;以RTP作为语言和视频的载体。联网系统在进行音视频传输及…

AQS和ReentrantLock还能这样理解?

1.公平锁和非公平锁 1.1含义 公平锁:在竞争环境下&#xff0c;先到临界区的线程比后到的线程一定更快地获取得到锁。非公平锁:先到临界区的线程未必比后到的线程更快地获取得到锁。 1.2如何自我实现 公平锁实现&#xff1a;可以把竞争的线程放在一个先进先出的队列上。只要…

webpack plugin

1、基本写法及使用 这里用到 emit 钩子 及make 钩子&#xff0c;前者是串行后者是并行 /*** 1.webpack加载webpack.config.js中所有配置&#xff0c;此时就会new TestPlugin()&#xff0c;执行插件的constructor2.webpack创建compiler对象3.遍历所有plugins中插件&#xff0…

404 - File or directory not found.

iis部署的时候容易出现以下错误&#xff0c;造成的主要原因可能是IIS没有安装好某个组件或插件: 04-找不到文件或目录。 您要查找的资源可能已被删除、名称已更改或暂时不可用。 如果遇到该问题&#xff0c;安装iis的时候记得安装以下

AIGC ChatGPT4总结SQL优化细节操作

数据库SQL优化是一个复杂的过程,它通常涉及到许多不同的技术和方法。以下是一些常用的SQL优化策略: 1. **索引使用**:索引可以极大地加速查询速度。但是,索引并不总是有好处的,因为它们需要额外的空间来存储,并且在插入和更新数据时可能会减慢速度。因此,选择正确的字段…

【C++】类和对象——构造函数和析构函数

今天要学习两个特殊的函数&#xff0c;分别是构造函数和析构函数&#xff0c;它们究竟有什么用呢&#xff1f; 比如说&#xff0c;我们先写一个简单的日期的类 class Date { public:void Init() {_year 1;_month 1;_day 1;}void Print() {cout << _year << &qu…

字符串和内存函数(2)

文章目录 2.13 memcpy2.14 memmove2.15 memcmp2.16 memset 2.13 memcpy void* memcpy(void* destination, const void* source, size_t num); 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。如果so…

企业计算机服务器中了locked勒索病毒怎么办,勒索病毒解密恢复

计算机网络为企业的生产生活提供了极大帮助&#xff0c;让企业逐步走向数字化办公&#xff0c;但随之而来的网络安全威胁也不断增多&#xff0c;网络勒索病毒病毒攻击企业计算机的事件频发&#xff0c;并且攻击加密手段也在不断提升。近期&#xff0c;云天数据恢复中心再次接到…

接口测试 —— requests 的基本了解

● requests介绍及安装 ● requests原理及源码介绍 ● 使用requests发送请求 ● 使用requests处理响应 ● get请求参数 ● 发送post请求参数 ● 请求header设置 ● cookie的处理 ● https证书的处理 ● 文件上传、下载 requests介绍 ● requests是python第三方的HTTP…

python -opencv 中值滤波 ,均值滤波,高斯滤波实战

python -opencv 中值滤波 &#xff0c;均值滤波&#xff0c;高斯滤波实战 cv2.blur-均值滤波 cv2.medianBlur-中值滤波 cv2.GaussianBlur-高斯滤波 直接看代码吧&#xff0c;代码很简单&#xff1a; import copy import math import matplotlib.pyplot as plt import matp…

第二十章 多线程

20.2创建线程 20.2.1继承Thread类 Thread类是Java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建议Thread实例。 public class ThreadTest extedns Thread{} run方法格式&#xff1a; public void run(){} 20.1让线…

论设备管理的发展趋势及对策

作者&#xff1a;韩平 设备是企业生产要素的一个重要组成部分&#xff0c;是企业进行生产活动的物质硬件基础&#xff0c;也是决定企业生产效能的重要因素之一。 设备管理又称设备工程&#xff0c;是根据企业生产经营目标&#xff0c;为了提高设备效能&#xff0c;在调查研究…