在固定工具中调用函数时发生分段错误
Segmentation fault occurs when calling function in the Pin tool
我目前正在构建一个 Pin 工具,该工具基于这篇博文检测来自 Linux 应用程序的未初始化读取。
您还可以从博客中查看作者的代码。
由于这个是针对Windows的,我试图创建一个与Linux兼容的。但是当我使用应用程序执行我的 Pin 工具时,发生了分段错误。奇怪的是,错误发生在调用函数时(错误发生在引脚工具调用taint_define
函数中的函数taint_get
时),而不是因为访问未初始化的堆指针或此类一般分段错误点。
分段错误点如下所示:
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 工具,该工具基于这篇博文检测来自 Linux 应用程序的未初始化读取。
这并不能真正回答您的问题,您可能有其他原因来学习 Pin 工具,但是......
我们发现基于 Pin 的工具不足以检测非玩具程序。如果您的目标是检测未初始化的内存读取,请考虑使用内存清理器。
readb4write只有32位。我不知道您是如何编译它的,但即使您添加 -m32,它可能仍然不起作用。这是我的情况,但我正在 Windows 上运行它。
您只能通过查看例如注释来判断它是 32 位:"//我们使用 128k 的0x8000块来污染"
0x8000 x 128kb = 4294967296这是 32 位进程的虚拟范围限制。
在 x64 上,您需要taint_get方法中满足 48 位地址的需求。这仍然是一个幼稚的实现,但其他
一切都是如此
typedef UINT64 * TTaint[0x80000];
TTaint *taintTable[0x10000] = { 0 };
inline UINT64 *taint_get(ADDRINT addr)
{
UINT64 chunkAddress = addr / 0x20000; //get number address of 128kb chunk.
UINT64 firstLevAddr = chunkAddress / 0x10000;
UINT64 secondLevelAddr = chunkAddress % 0x10000;
TTaint *taint = NULL;
if (taintTable[firstLevAddr] == NULL){
taintTable[firstLevAddr] = (TTaint*)W::VirtualAlloc(NULL, sizeof(TTaint),
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
}
taint = taintTable[firstLevAddr];
// allocate memory to taint these memory pages
if ((*taint)[secondLevelAddr ] == NULL) {
// we need an 16kb page to track 128k of memory
(*taint)[secondLevelAddr] = (UINT64 *)W::VirtualAlloc(NULL, 0x20000 / 8,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
}
return (*taint)[secondLevelAddr];
}
此外,大多数(如果不是全部)变量需要是UINT64而不是UINT32。32 需要更改为 64。
还有一个问题我还没有解决。有一行用于检测访问未初始化内存的指令是否属于正在检查的程序。它不太可能在 x64 中仍然有效:
(知识产权和0xfff00000) == 0x00400000)
如果我设法让它工作,我将在 github 中发布代码。
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?