gpt4 book ai didi

c++ - 任何 Hook 函数的单一接口(interface)

转载 作者:行者123 更新时间:2023-11-27 23:54:03 25 4
gpt4 key购买 nike

我正在编写一个简单的 Dll 注入(inject)和 Hook 程序,当我为 CreateFileA 手动声明要 Hook 的函数时,一切都很好:

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 - 是原始函数的地址。但是它会使注入(inject)了 Dll 的应用程序崩溃。我想我的代码损坏了堆栈或其他东西。我究竟做错了什么?希望我的解释有意义。

最佳答案

ebx 不是易变的,你不能直接写入它,你必须保存/恢复原始值。

编写一个通用的钩子(Hook)函数会很困难,因为 32 位 Windows ABI 有 3 个调用约定; stdcall(被调用者清理堆栈)、cdecl(调用者清理堆栈)和 fastcall(寄存器中的前两个参数,但在公共(public) API 中使用不多)。

如果您只想记录函数调用,您可能会这样做:

push esp
push pfnFuncAddr
call mylogger ; assumed to be stdcall in this case, it can also change the jump
jmp eax

FARPROC __stdcall mylogger(FARPROC 函数, SIZE_T stackaddress) { ...;返回函数; }(记住 esp 已经改变,所以如果你想记录堆栈的内容,你必须将堆栈参数调整 8+4 个字节。)如果你关心 fastcall 你也必须压入寄存器,但通用记录器无法知道第一个参数是在堆栈上还是在寄存器中。

关于c++ - 任何 Hook 函数的单一接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43969712/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com