【问题标题】:IAT Hooking ExitProcess on own processIAT 在自己的进程上挂钩 ExitProcess
【发布时间】:2013-02-10 13:51:03
【问题描述】:

我想问一个关于 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),尽管它也失败了。

ExitProcess 的 GetProcAddress 确实在 PE 内返回了一个指针,我尝试通过 loadlibrary 强制加载 kernel32.dll(尽管它应该自动加载),尽管结果是一样的。

可能是什么问题?

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;

非常感谢您,祝您有美好的一天!

【问题讨论】:

  • 完全不清楚你的程序使用什么样的运行时支持库。其中将包含终止程序的代码。它可以是一个单独的 DLL,在 C/C++ 中很常见。程序通过简单地从入口点返回或调用 TerminateProcess 来结束自己。
  • @Hans:程序几乎总是通过调用ExitProcess 来结束自己。入口点永远不会返回。 (大多数运行时支持库都允许用户提供某种main函数返回,然后运行时调用ExitProcess,但返回的用户提供的main函数不是入口点)
  • 如果你正在使用 crt,你仍然可以使用 atexit(),或者你可能更喜欢做 iat hooking,因为这很有趣。我有一个工作代码,但不幸的是,当 Windows 拧紧磁盘时它丢失了

标签: winapi hook portable-executable thunk api-hook


【解决方案1】:

如果您的应用没有静态调用ExitProcess(),例如根本没有调用它(甚至没有被您的应用的RTL调用)或者它是通过GetProcAddress()动态加载的,那么它就不会出现在您的应用程序的 IMPORTS 表。 IMPORTS 表仅列出您的应用静态链接到的函数。这可能是您的代码找不到它的原因。使用像 PEDUMP 或 DependancyWalker 这样的实用程序来确保您的应用实际上是静态链接到 ExitProcess()。例如,在我的开发环境(C++Builder XE2)中,如果我创建一个控制台项目,则在 IMPORTS 表中找不到ExitProcess(),但如果我创建了一个 GUI 项目,则可以找到它。不同之处在于这两种类型的项目在底层使用了不同的 RTL,因此显然控制台 RTL 在应用程序终止时不使用ExitProcess()

【讨论】:

  • 我个人从未见过不静态调用ExitProcess() 的应用程序。
  • 谢谢雷米!确实是这样,直到现在我一直认为 CRT 会自动调用 ExitProcess 虽然我猜在这种情况下并非如此,通过它调用 exit() 的代码调用 doexit() 等......直到它到达一些类似于 __CRTDoExit() 的下划线函数,它处理程序的转义。我猜这些实际上都不是指向 ExitProcess 的指针,或者它们是在运行时评估的。
  • 您必须查看 CRT 源代码(如果供应商提供它),或者在 ExitProcess() 本身内放置一个断点以查看它是否被调用,但听起来确实如此不是。
猜你喜欢
  • 1970-01-01
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多