如何使用英特尔PIN获取内存操作值?

时间:2018-01-02 19:29:44

标签: c++ intel intel-pin

我正在使用英特尔PIN来修改系统中的内存分配。

我无法找到一种方法来获取内存指令下的实际值。

VOID Instruction(INS ins, VOID *v) {
    UINT32 memOperands = INS_MemoryOperandCount(ins)
    for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
        if (INS_MemoryOperandIsRead(ins, memOp)) {
            INS_InsertPredicatedCall(
                                 ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,
                                 IARG_INST_PTR,
                                 IARG_MEMORYOP_EA, memOp,
                                 IARG_END);
        }
        if (INS_MemoryOperandIsWritten(ins, memOp)) {
             INS_InsertPredicatedCall(
                                 ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite,
                                 IARG_INST_PTR,
                                 IARG_MEMORYOP_EA, memOp,
                                 IARG_END);
        }
    }
}

VOID RecordMemRead(VOID * ip, VOID * addr) {
    if (!Record) return;
    printf("%p: R %p\n", ip, addr);
}


VOID RecordMemWrite(VOID * ip, VOID * addr) {
    if (!Record) return;
    printf("%p: R %p\n", ip, addr);
}

据我所知,这只打印指令指针和操作数的寄存器地址。那是对的吗?如果是这样,我怎样才能获得该寄存器的值?

最终,我要做的是拦截静态和堆变量的所有赋值,并将它们转换为一些过程调用以将值保存在Google Bigtable上。

1 个答案:

答案 0 :(得分:1)

  

据我所知,[...]打印指令指针

是的,由于IARG_INST_PTR

  

和操作数的寄存器地址

不,你得到的是操作数的EA(有效地址),定义为:

Effective Address = Displacement + Base_Reg + Index_Reg * Scale

假设您有以下指令(Intel语法):

mov eax, [ebx+ecx+0xf]

源操作数(右操作数)的EA是[ebx+ecx+0xf]的计算地址,如果使用IARG_MEMORYOP_EA,则不会获得EA的每个组件的值。

由于您只想跟踪堆和静态变量分配,您可能对&#34;组件&#34;不感兴趣。的操作数。

  

最终,我要做的是截取所有作业   static和heap变量并将它们转换为某些过程调用   将值保存在Google Bigtable上。

这不是一件容易的事。

您可以使用RTN_xxx函数来跟踪对内存分配和解放函数的调用(通常为malloc()free())。我认为PIN源有一个例子。

对于malloc(),您可以追踪返回的指针和分配的大小(例如,将其放在std :: map上)。每次写入时,检查它是否属于您的一个分配范围。 对于每个free(),从地图中删除指针。

对于静态变量,您可以使用IMG_AddInstrumentFunction跟踪已加载的模块,并查看是否在可执行文件的某个部分中发生了写入。