IAT перехватывает ExitProcess на собственный процесс

Я хотел бы задать вопрос относительно подключения IAT к моему собственному процессу.

В настоящее время я пытаюсь подключить ExitProcess, чтобы он запускал определенную функцию перед любым вызовом ExitProcess, и я сталкиваюсь с некоторыми проблемами.

Я просматриваю PE во время выполнения, просматривая IMAGE_IMPORT_DESCRIPTOR , найдя там kernel32.dll (который является первым .dll), я просматриваю его THUNK_DATA-s по имени, пытаясь найти там ExitProcess, хотя безуспешно.

Регистрация функций, это функции, которые там находятся -

GetModuleHandleA
GetProcAddress
LoadLibraryA
GetModuleFileNameW
FreeLibrary
VirtualQuery
GetProcessHeap
HeapFree
HeapAlloc
GetSystemTimeAsFileTime
GetCurrentThreadId
GetCurrentProcessId
QueryPerformanceCounter
IsProcessorFeaturePresent
WideCharToMultiByte
MultiByteToWideChar
LoadLibraryW
lstrlenA
LoadLibraryExW
GetLastError
RaiseException
IsDebuggerPresent
DecodePointer
EncodePointer
GetModuleHandleW

Хотя ExitProcess нигде не находится внутри .

Я попытался перечислить по указателям функций вместо имен (используя thunkdata вместо originalthunkdata), хотя это также не удалось.

GetProcAddress для ExitProcess возвращает указатель в PE, и я попытался принудительно загрузить kernel32.dll (хотя он должен загружаться автоматически) с помощью loadlibrary, хотя результат тот же.

В чем может быть проблема ?

HMODULE hMod = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pImgDosHeaders = (PIMAGE_DOS_HEADER)hMod;
PIMAGE_NT_HEADERS pImgNTHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders + pImgDosHeaders->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)pImgDosHeaders + pImgNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
UINT indx = 0;
while(strcmpi((PCHAR)((LPBYTE)pImgDosHeaders + pImgImportDesc[indx].Name), "kernel32.dll")) { ++indx; };
PIMAGE_THUNK_DATA pImgThunkData = (PIMAGE_THUNK_DATA)((LPBYTE)pImgDosHeaders +pImgImportDesc[indx].OriginalFirstThunk);
PIMAGE_IMPORT_BY_NAME pImgImportByName = NULL;
for(;pImgThunkData->u1.Function; ++pImgThunkData)
{
    pImgImportByName = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)pImgDosHeaders + pImgThunkData->u1.AddressOfData);
    !strcmpi("ExitProcess",pImgImportByName->Name) ? cout << "ExitProcess Found" : false;
}
return true;

Большое спасибо и хорошего дня!


person Danny Shemesh    schedule 10.02.2013    source источник
comment
Совершенно непонятно, какую библиотеку поддержки времени выполнения использует ваша программа. Который будет содержать код для завершения программы. Это может быть отдельная DLL, распространенная в C/C++. И программы заканчивают работу, просто возвращаясь из точки входа или вызывая TerminateProcess.   -  person Hans Passant    schedule 10.02.2013
comment
@Hans: Программы почти всегда заканчиваются вызовом ExitProcess. Точка входа никогда не возвращается. (Большинство библиотек поддержки среды выполнения позволяют какой-либо основной функции, предоставленной пользователем, возвращаться, а затем среда выполнения вызывает ExitProcess, но возвращаемая пользователем функция main не является точкой входа)   -  person Ben Voigt    schedule 10.02.2013
comment
вы по-прежнему можете использовать atexit(), если вы используете crt, или вам может хотеться вместо этого делать перехват iat, потому что это интересно. У меня был рабочий код, но, к сожалению, он потерялся, когда Windows скрутила диск.   -  person sherpya    schedule 11.02.2013


Ответы (1)


Если ваше приложение не вызывает ExitProcess() статически, например, если оно вообще не вызывается (даже с помощью RTL вашего приложения) или если оно загружается динамически через GetProcAddress(), то оно не будет присутствовать в таблице IMPORTS вашего приложения. В таблице IMPORTS перечислены только функции, на которые ваше приложение ссылается статически. Вероятно, поэтому ваш код его не находит. Используйте такую ​​утилиту, как PEDUMP или DependancyWalker, чтобы убедиться, что ваше приложение действительно статически связывается с ExitProcess(). Например, в моей среде разработки (C++Builder XE2), если я создаю консольный проект, ExitProcess() не будет найден в таблице IMPORTS, но если вместо этого я создам проект с графическим интерфейсом, он будет найден. Разница в том, что два типа проектов используют разные RTL под капотом, поэтому очевидно, что RTL консоли не использует ExitProcess() при завершении работы приложения.

person Remy Lebeau    schedule 11.02.2013
comment
Я лично никогда не видел приложения, которое не вызывает ExitProcess() статически. - person JosephH; 11.02.2013
comment
Спасибо Реми! Это действительно так, до сих пор я думал, что CRT автоматически вызовет ExitProcess, хотя я думаю, что это не так в этом сценарии, следуя коду, который вызывает exit(), который вызывает doexit() и т. д. ... до тех пор, пока он не достигает некоторой подчеркнутой функции, похожей на __CRTDoExit(), которая обрабатывает выход из программы. Я предполагаю, что ни один из них на самом деле не является указателем на ExitProcess или оценивается во время выполнения. - person Danny Shemesh; 11.02.2013
comment
Вам нужно будет посмотреть исходный код CRT (если поставщик предоставляет его) или поставить точку останова внутри самого ExitProcess(), чтобы увидеть, вызывается ли он, но это звучит так, как будто это не так. - person Remy Lebeau; 11.02.2013