【发布时间】:2018-03-20 07:03:58
【问题描述】:
我正在使用英特尔 PIN 修改我的应用程序中的指令。我使用此链接中的 Safecopy() 示例作为参考:
https://software.intel.com/sites/landingpage/pintool/docs/81205/Pin/html/index.html#SafeCopy
我有以下示例 C 程序:
int main()
{
asm(".byte 0x16");
return 0;
}
0x16 在 x86_64 中是非法的,当我运行可执行文件时,它会按预期显示以下错误:
Illegal instruction (core dumped)
我有一个 pintool,它将上述可执行文件作为输入并修改非法指令 0x16 以执行其他操作。
我的 Pintool 如下:
#include "pin.H"
#include <iostream>
#include <fstream>
using namespace std;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI");
FILE * op;
//====================================================================
// Analysis Routines
//====================================================================
VOID analysis_routine(VOID *ip, UINT32 size)
{
fprintf(op,"16 came to analysis routine\n\n");
}
//====================================================================
// Instrumentation Routines
//====================================================================
VOID Instruction(INS ins, void *v)
{
UINT8 opcodeBytes[15];
UINT64 fetched = PIN_SafeCopy(&opcodeBytes[0],(void *)INS_Address(ins),INS_Size(ins));
if (fetched != INS_Size(ins))
fprintf(op,"\nBad\n");
else
{
if(opcodeBytes[0]==0x16)
{
fprintf(op,"\n16 came to instrumentation routine\n");
INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, IARG_INST_PTR, IARG_UINT64, INS_Size(ins) , IARG_END);
INS_Delete(ins);
}
}
}
VOID Fini(INT32 code, VOID *v)
{
}
INT32 Usage() {
PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char *argv[])
{
op = fopen("test.out", "w");
if (PIN_Init(argc, argv))
return Usage();
PIN_InitSymbols();
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
PIN_StartProgram();
return 0;
}
根据我的理解,每次遇到新指令时都会执行检测例程指令,并且根据我的代码,在执行指令之前调用分析例程,因为我在检测函数中使用 IPOINT_BEFORE 参数来调用分析常规。因此,我正在检查我的操作码,如果它是 0x16,那么我正在调用我的分析例程并删除我的原始指令。由于该指令是非法的并且已被删除,因此我的跟踪应该继续进行,没有任何问题。
但是,即使使用此逻辑,似乎我的非法指令正在执行,我的程序崩溃并给出相同的非法指令错误。我无法理解这个问题,因为我似乎在执行指令之前删除了指令,并且我使用的是 Pin 教程中的相同示例。
如果我调用任何错误的任何想法?如果我在上面的任何地方错了,也请纠正我。根据我的理解,检测例程在指令执行之前被调用,因此我也可以在那个时候修改指令。如果我错了,请纠正我。
【问题讨论】:
-
您是否成功替换了正确地址的正确字节?你确定你只是替换给你带来麻烦的一个字节吗?您是否仅替换该单个字节而不替换其他字节模式? 0x16 本身可能不是合法指令,但您如何确保它不会被解释为更大指令的一部分?