Windows


Перехват API-вызовов с использованием раздела импорта - часть 2


// заменяем адреса исходных функций адресами своих функций
for (; pThunk->u1.Function; pThunk++)
{

// получаем адрес адреса функции
PROC* ppfn = (PROC*) &pThunk->u1.Function;

// та ли это функция, которая нас итересует?
BOOL fFound = (*ppfn == pfnCurrent);

// см. текст программы-примера, в котором
// содержится трюковый код для Windows 98

if (fFound)
{

// адреса сходятся, изменяем адрес в разделе импорта
WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL );

return; // получилось, выходим

}

}

// если мы попали сюда, значит, в разделе импорта
// нет ссылки на нужную функцию

}

Чтобы понять, как вызывать эту функцию, представьте, что у нас есть модуль с именем DataBase.exe. Он вызывает ExitProcess из Kernel32.dll, но мы хотим, чтобы он обращался к MyExitProcess в нашем модуле DBExtend.dll, Для этого надо вызвать ReplaceMTEntryInOneMod следующим образом.

PROC pfnOrig = GctProcAddress(GetModuleHandle("Kernel32"), "ExitProcess");
HMODULE hmodCaller = GetModuleHandle("DataBase.exe");

void RoplaceIATEntryInOrioMod(
"Kernel32.dll", // модуль, содержащий ANSI-функцию
pfnOrig, // адрес исходной функции в вызываемой DLL
MyExitProcess, // адрес заменяющей функции
hmodCaller); // описатель модули, из которого надо вызывать новую функцию

Первое, что делает ReplacelATEntryInOneMod, - находит в модуле hmodCalIer раздел импорта. Для этого она вызывает ImageDirectoryEntryToData и передает ей IMAGE_ DlRECTORY_ENTRY_IMPORT. Если последняя функция возвращает NULL, значит, в модуле DataBase.exe такого раздела нет, и на этом все заканчивается

Если же в DataBase.exe раздел импорта присутствует, то ImageDirectoryEntryToData возвращает его адрес как укачатель типа PIMAGE_IMPORT_DESCRIPTOR. Тогда мы должны искать в разделе импорта DLL, содержащую требуемую импортируемую функцию В данном примере мы ищем идентификаторы, импортируемые из Kernel32.dll (имя которой указывается в первом параметре ReplacelATEntryInOneMod), В цикле for сканируются имена DLL. Заметьте, что в разделах импорта все строки имеют формат ANSI (Unicode не применяется). Вот почему я вызываю функцию lstrcmpiA, а не макрос lstrcmpi.




Начало  Назад  Вперед



Книжный магазин