Ошибка сегментации возникает при вызове функции в инструменте Pin

В настоящее время я создаю инструмент Pin, который обнаруживает неинициализированные чтения из приложения Linux, основываясь на этом Сообщение блога.
Вы также можете увидеть авторский код из блога.

Так как это для Windows, я попытался создать Linux-совместимый.
Но когда я запускаю свой инструмент 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.
И, мой код инструмента прикреплен Вот

2

Решение

В настоящее время я создаю инструмент Pin, который обнаруживает неинициализированные чтения из приложения Linux на основе этого сообщения в блоге.

Это на самом деле не отвечает на ваш вопрос, и у вас могут быть другие причины изучить инструмент Pin, но …

Мы обнаружили, что основанные на булавках инструменты не подходят для инструментов, не являющихся игрушками. Если ваша цель — обнаружить неинициализированные чтения из памяти, подумайте об использовании Дезинфицирующее средство для памяти.

0

Другие решения

readb4write только 32-битный. Я не знаю, как вы его компилируете, но даже если вы добавите -m32, он все равно может не сработать. Это то, что произошло в моем случае, но я запускаю его на Windows.
Вы можете сказать, что он 32-битный, только взглянув, например, на комментарий: «// мы используем 0x8000 кусков 128k, чтобы испортить»
0x8000 x 128kb = 4294967296, что является пределом виртуального диапазона 32-битного процесса.
На x64 вам нужно обслуживать 48-битные адреса в методе taint_get. Это все еще наивная реализация, но и все остальное

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, если мне удастся заставить его работать.

0

По вопросам рекламы [email protected]