我正在使用英特尔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上。
答案 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
跟踪已加载的模块,并查看是否在可执行文件的某个部分中发生了写入。