【发布时间】:2017-05-15 19:54:38
【问题描述】:
我正在编写一个简单的 Dll 注入和挂钩程序,当我手动声明函数以像这样为 CreateFileA 挂钩时,一切都很好:
HANDLE WINAPI Hook_CreateFileA(
LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile
)
{
...
return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
但是现在我需要编写一个函数来处理来自 kernel32.dll 的任何函数,例如。这意味着除了函数的名称和地址之外,我对函数一无所知。
我对调用约定略知一二——函数参数按直接顺序推送(__stdcall),然后调用函数。我尝试编写一个 __declspec(naked) 函数,如下所示:
PVOID __declspec(naked) HookAnyFunction()
{
/* do something */
__asm {
mov ebx, [esp]
add esp, 4
call pfnFuncAddr
sub esp, 4
mov[esp], ebx
ret
}
}
pfnFuncAddr - 是原始函数的地址。但它会使用注入的 Dll 使应用程序崩溃。我猜我的代码损坏了堆栈或其他东西。我究竟做错了什么?希望我的解释有意义。
【问题讨论】:
-
好吧,你正在破坏调用者的
ebx寄存器,这可能会导致崩溃。请注意,不确定有什么好的方法。 -
如果你想控制 after
pfnFuncAddr你需要将原始返回地址(在 [esp] 中)替换为分配的可执行内存存根,它从 call 对您的呼叫后处理程序的指令。然后必须是一些数据——保存的原始返回地址、函数名、保存的参数。结果在 post 处理程序中,您获得了此块的地址(它将是存根中 call 指令的返回地址) - 可以发布日志,包括返回值,如果需要,可以更改它。最后释放存根块并返回原始返回地址。 -
存根块(所有它都具有相同的大小)最好在开始时在大的可执行内存块中分配,并通过 InterlockedPopEntrySList / InterlockedPushEntrySList 实现分配/释放我>
标签: c++ windows hook dll-injection