【发布时间】:2013-11-22 05:15:13
【问题描述】:
我目前正在构建一个 Pin 工具,用于检测来自 Linux 应用程序的未初始化读取,基于此 blog post。
也可以从博客中看到作者的代码。
因为这个是针对 Windows 的,所以我尝试创建一个兼容 Linux 的。
但是当我使用应用程序执行我的 Pin 工具时,会发生分段错误。
奇怪的是调用函数时发生故障(当pin工具调用taint_get函数时发生故障,该函数在taint_define函数中),不是因为访问未初始化的堆指针或此类点一般分段错误。
分段错误的点是这样的:
VOID Instruction(INS ins, VOID *v)
{
Uninit_Instruction(ins, v);
}
void Uninit_Instruction(INS ins, void* v)
{
// check if the stack pointer is altered (i.e. memory is allocated on the
// stack by subtracting an immediate from the stack pointer)
if(INS_Opcode(ins) == XED_ICLASS_SUB &&
INS_OperandReg(ins, 0) == REG_STACK_PTR &&
INS_OperandIsImmediate(ins, 1))
{
// insert call after, so we can pass the stack pointer directly
INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)taint_undefined,
IARG_REG_VALUE,
REG_STACK_PTR,
IARG_ADDRINT, (UINT32) INS_OperandImmediate(ins, 1),
IARG_END);
}
UINT32 memOperands = INS_MemoryOperandCount(ins);
for (UINT32 memOp = 0; memOp < memOperands; memOp++)
{
if (INS_MemoryOperandIsRead(ins, memOp))
{
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)taint_check,
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_MEMORYREAD_SIZE,
IARG_END);
}
if (INS_MemoryOperandIsWritten(ins, memOp))
{
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)taint_define,
IARG_MEMORYOP_EA, memOp,
IARG_MEMORYWRITE_SIZE,
IARG_END);
}
}
}
回调函数如下所示:
// Taint this address as written
void taint_define(ADDRINT addr, UINT32 size)
{
// Debug purpose
TraceFile << "taint_define: " << addr << ", " << size << endl;
// taint the addresses as defined, pretty slow, but easiest to implement
for (UINT32 i = 0; i < size; i++)
{
//TraceFile << "taint_define_loop size: " << size << endl;
UINT32 *t = taint_get(addr + i);
TraceFile << "after taint_get" << endl;
UINT32 index = (addr + i) % 0x20000;
// define this bit
t[index / 32] |= 1 << (index % 32);
}
}
inline UINT32* taint_get(ADDRINT addr)
{
// Debug purpose
TraceFile << "taint_get: " << addr;
// allocate memory to taint these memory pages
if(taint[addr / 0x20000] == NULL) {
// we need an 16kb page to track 128k of memory
/*
taint[addr / 0x20000] = (UINT32 *) W::VirtualAlloc(NULL, 0x20000 / 8,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
*/
taint[addr / 0x20000] = (UINT32*)malloc(0x20000/8);
}
return taint[addr / 0x20000];
}
输出如下:
C:Tool (or Pin) caused signal 11 at PC 0x7fcf475e08a4
segmentation fault (core dumped)
日志在这里。
Watched Image count: 0x1
WatchedImage: unread_3vars
Uninit_Image
Uninit_Image
Thread start
taint_define: 0x7fff06930d58, 0x8
我目前正在开发 Fedora 核心 17 x86-64、gcc 4.7.2 和 Pin 2.12-58423。
而且,我的pin工具代码附在here
【问题讨论】:
-
您应该在
-Wall -Wextra - pedantic上使用所有警告进行编译,然后修复代码,直到编译器不再发出警告。然后使用选项-g使用调试符号编译并使用调试器(例如gdb)运行程序。然后它会向您显示程序崩溃的确切位置,并允许您检查正在使用的变量。
标签: c++ c segmentation-fault intel-pin