Я сделал пин-инструмент для вывода вызовов Win32 CreatFile (в моем случае CreateFileW) и его возвращаемых значений. Это выглядит так:
/* ... */
VOID Image(IMG img, VOID *v)
{
RTN cfwRtn = RTN_FindByName(img, "CreateFileW");
if (RTN_Valid(cfwRtn))
{
RTN_Open(cfwRtn);
RTN_InsertCall(cfwRtn, IPOINT_BEFORE, (AFUNPTR)CreateFileWArg,
IARG_ADDRINT, "CreateFileW",
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_InsertCall(cfwRtn, IPOINT_AFTER, (AFUNPTR)CreateFileWafter,
IARG_FUNCRET_EXITPOINT_VALUE, IARG_END);
RTN_Close(cfwRtn);
}
}
/* ... */
VOID CreateFileWArg(CHAR * name, wchar_t * filename)
{
TraceFile << name << "(" << filename << ")" << endl;
}
VOID CreateFileWafter(ADDRINT ret)
{
TraceFile << "\tReturned handle: " << ret << endl;
}
Это дает интересные результаты. Например, в небольшой программе, которая просто открывает существующий файл и больше ничего не делает, она дает:
CreateFileW(file.txt)
Returned handle: 0
CreateFileW(file.txt)
Returned handle: 0x74
Returned handle: 0x74
Много аномалий. 1.) Почему есть два фактических звонка? 2.) Если я не ошибаюсь, CreateFile никогда не должен возвращать 0. 3.) После второго вызова он возвращается дважды (?)
Я также пытался создать простую программу на С ++, которая непосредственно вызывает CreateFileW один раз, результат:
CreateFileW(file.txt)
Returned handle: 0
CreateFileW(file.txt)
Returned handle: 0xffffffff
Returned handle: 0xffffffff
Файл, который я пытался открыть, не существует, поэтому возвращаемое значение (-1 == INVALID_HANDLE_VALUE), по крайней мере, является правильным.
Есть идеи? Заранее спасибо!
Хорошо, через некоторое время я наконец выяснил причины этих проблем.
Ну, документация PIN-кода гласит:
ПРИМЕЧАНИЕ: IPOINT_AFTER реализуется путем инструментирования каждой инструкции возврата в подпрограмме. Пин пытается найти все инструкции по возврату, но успех не гарантирован
Если вы дампаете адрес функции при возврате, оказывается, что 0 не вернулся из CreateFileW. Он возвращается из другой функции, в которую CreateFileW вызывает. Это ошибочное поведение ПИН-кода может быть исправлено путем переноса метода CreateFileW в вашу собственную версию (сброс параметров, вызов исходной функции, возврат возвращаемого значения).
Оказывается, что в моей системе CreateFileW вызывает функцию Kernelbase.dll, которая имеет точно такое же имя. Поскольку я инструктировал подпрограммы по их имени, это правильное поведение. Проверка имени образа против kernel32.dll решила эту проблему.
Я бы предложил перехватить его на уровне системных вызовов, а не на одном из этих неуверенных промежуточных уровней (в какой бы библиотеке он ни находился). В Windows номера системных вызовов и интерфейс не являются общедоступными, но их легко найти в любом случае.