修改PIN中的应用程序指令

时间:2017-10-09 06:40:51

标签: c++ c assembly intel-pin

我正在使用英特尔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教程中的相同示例。

如果我调用任何错误的任何想法?如果我在上面的任何地方错了,请纠正我。根据我的理解,在执行指令之前调用检测例程,因此我也可以修改时间指令。如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:1)

我不知道这里出了什么问题,但这就是我要做的事情:我首先要在仪器例程中打印更多关于指令的信息。< / p>

  • 多长时间?
  • 这条指令有什么地址?在测试程序中打印main()的地址,看看两者是否彼此靠近。
  • 其他指令字节是什么?它们恰好是与非法字节后面的指令匹配的字节吗?

的方法,另外:

  • 确保每次打印后刷新输出文件,以确保非法指令失败不会掩盖您的调试打印
  • 我建议您抓住您的程序可能获得的SIGILL信号,并确保它在有或没有Pin的情况下发生在同一个地方。

答案 1 :(得分:0)

您需要意识到INS_Delete()是在检测时调用的,即在实际执行指令之前,也是在调用检测例程之前调用的。事件发生的顺序如下:

INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, ...);
INS_Delete(ins);
analysis_routine(); /* <= BOOM ! ins had been deleted just before... */

当调用INS_Delete(ins)时,您需要删除所有与它一起使用的检测,否则您的工具不一致。假设仪器仍然存在,那么与仪器例程相关联的指令将不是预期的指令,因此会发生崩溃。

为了更好地理解这一点(第一次就不容易理解),您可能想再次阅读pin works的内容。

编辑:根据该工具随附的一些官方pintools(请参阅下面的评论),仪器然后删除模式是PIN的常规模式。