我一直试图在ExitProcess上编写一个蹦床挂钩,以求有趣。挂钩的代码(一个消息框)可以很好地执行,但是当需要返回ExitProcess时,我会遇到访问冲突。我已经多次阅读自己的代码,看不到任何错误。我将旧函数的序言存储在字节数组中,并在我修补的地址之后立即将jmp添加到该地址。我会用这种错误的方式吗?
#include "main.h"
PVOID TrampolineAddress;
BYTE TrampolineBytes[10] = { 0, 0, 0, 0, 0, 0xE9, 0, 0, 0, 0 };
void ExitProcessNew(UINT uExitCode)
{
MessageBox(NULL, "Exiting!", "Exiting!", 0);
_asm
{
push uExitCode;
call TrampolineAddress;
}
}
int main()
{
memcpy(&TrampolineBytes, &ExitProcess, 5);
*(DWORD*)&TrampolineBytes[6] = (DWORD)((DWORD)&ExitProcessNew) - (DWORD)&ExitProcess;
TrampolineAddress = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(TrampolineAddress, TrampolineBytes, 10);
BYTE PatchBytes[] = { 0xE9, 0, 0, 0, 0 };
*(DWORD*)&PatchBytes[1] = (DWORD)((DWORD)&ExitProcessNew) - (DWORD)&ExitProcess - 5;
BOOL writeSuccess = WriteProcessMemory(GetCurrentProcess(), &ExitProcess, PatchBytes, sizeof(PatchBytes), NULL);
ExitProcess(0);
printf("%d", GetLastError());
getchar();
}
答案 0 :(得分:0)
我花了很长时间尝试使您的代码正常工作,但最终我放弃了,决定仅仅向您展示有效的代码而不是尝试修复您的代码更容易。您的逻辑是有道理的,但我认为有几个小错误会导致失败。
因此,这是我使用很长时间的方法,该方法基于一个与我共享的名为Solaire的朋友的代码:
常规挂钩/绕行功能:
bool Hook(BYTE* src, BYTE* dst, int len)
{
if (len < 5) return false;
DWORD curProtection;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);
uintptr_t relativeAddress = ((uintptr_t)dst - (uintptr_t)src) - 5;
*src = 0xE9;
*(uintptr_t *)((uintptr_t)src + 1) = relativeAddress;
VirtualProtect(src, len, curProtection, &curProtection);
return true;
}
蹦床功能:
void * TrampolineHook(BYTE* src, BYTE* dst, int len)
{
// Make sure the length is greater than 5
if (len < 5) return 0;
// Create the gateway (len + 5 for the overwritten bytes + the jmp)
void* gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//Write the stolen bytes into the gateway
memcpy(gateway, src, len);
// Get the gateway to destination addy
uintptr_t gatewayRelativeAddr = ((uintptr_t)src - (uintptr_t)gateway) - 5;
// Add the jmp opcode to the end of the gateway
*(BYTE*)((uintptr_t)gateway + len) = 0xE9;
// Add the address to the jmp
*(uintptr_t *)((uintptr_t)gateway + len + 1) = gatewayRelativeAddr;
// Place the hook at the destination
Hook(src, dst, len);
return gateway;
}
您已经知道逻辑,因此我不需要解释代码,注释就足够了。
现在在下面,我们将定义与ExitProcess函数匹配的函数指针,并为模板加上“ t”前缀。
然后,我们创建该类型的指针,并为原始指针添加“ o”前缀,因为在运行代码后,我们将使用它来调用“原始”函数。然后,我们将流重定向到的实际函数的前缀为“ h”,表示“已连接”或其他任何内容。
主要代码:
typedef void(__stdcall* tExitProcess)(UINT);
tExitProcess oExitProcess;
void __stdcall hExitProcess(UINT uExitCode)
{
MessageBox(NULL, "Exiting!", "Exiting!", 0);
Sleep(1000);
return oExitProcess(uExitCode);
}
int main()
{
oExitProcess = (tExitProcess)TrampolineHook((BYTE*)&ExitProcess, (BYTE*)&hExitProcess, 5);
ExitProcess(0);
}
相当标准的过程,请尝试一下,并与您进行比较,希望对您有所帮助