简短回答:
是的,单步标志是 x86 架构的一部分,并且仍然通过处理器上下文的 eflags 组件在 Windows 7 中实现。
我已经成功下载了您的项目,在 Windows 8 上关闭 UAC 后,一切正常,无需修改。所以它也应该可以在 Windows 7 上运行。启动时VEH Hooking Test.exe
它显示两个消息框,在每个消息框之后我都会收到MessageBoxA
控制台输出,所以钩子起作用了。也许尝试在 Windows 7 上以管理员身份启动该程序?
长答案:
SEH
代表结构化异常处理,但您所描述的听起来更像VEH
- 向量异常处理。
VEH 挂钩是一种非常慢的挂钩方法,因此它不能真正用于性能关键的挂钩,例如图形挂钩,例如挂钩每秒点击多次。它通常用于一次性钩子。 VEH hooking 的目的是真正隐秘。别人的代码中没有写入内存,您也不必使用调试寄存器。
以下是我如何使用 C++ 实现它。
首先,您必须注册一个向量异常处理程序。这是该进程的全局异常处理程序。每个未处理且会传递到操作系统的抛出异常都将被此处理程序捕获。
PVOID pExHandler = AddVectoredExceptionHandler(1, VectoredHandler);
之后,您应该设置您所在页面的内存保护HOOK_LOCATION
(要挂钩的地址)在。我使用的新保护是PAGE_EXECUTE_READ|PAGE_GUARD
。受保护的页面会导致访问异常,并会自动解除保护。此异常不会由任何人处理,因此它将落入我们的向量处理程序。抛出异常后,页面可以再次访问。 (看创建保护页 http://msdn.microsoft.com/en-us/library/windows/desktop/aa366549(v=vs.85).aspx)
内存只能以页的形式进行保护(通常为 0x1000 字节长)。这就是为什么我们不仅不能保护钩子位置,而且会产生巨大的性能开销。
DWORD orgProt;
VirtualProtect(HOOK_LOCATION, 1, PAGE_EXECUTE_READ|PAGE_GUARD, &orgProt);
现在我们的异常处理程序。它可能是这样的:
LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS exc)
{
if (exc->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
{
// guard page exeption occured. guard page protection is gone now
if (HOOK_LOCATION == reinterpret_cast<long*>(exc->ContextRecord->Eip)) {
// hook location was hit! call any hook callbacks here
} else {
// hook was not hit and has to be refreshed. set single-step flag
exc->ContextRecord->EFlags |= 0x100;
}
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exc->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
{
// single-step exeption occured. single-step flag is cleared now
// set guard page protection
DWORD oldProt;
VirtualProtect(HOOK_LOCATION, 1, PAGE_EXECUTE_READ|PAGE_GUARD, &oldProt);
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
如果代码运行到受保护的内存页,它将引发保护页违规。我们检查是否处于挂钩位置。如果一切正常,我们可以调用钩子回调。如果我们不在正确的位置,我们需要以某种方式重新保护代码,但如果我们现在就这样做,我们就无法前进,并且总是在同一位置出现异常并使应用程序死锁。所以我们设置处理器单步标志。
现在,当收到单步异常时,我们可以再次设置防护保护,因为我们前进了一条指令。这样我们就可以始终保护目标页面并且不会错过任何钩子命中。
成本是在目标页面中执行的每条指令有两个异常和一个页面保护。不要尝试在附加调试器的情况下执行此操作。它会发疯的。
对于实际的实现,您可能需要同步对象来摆脱钩子而不会使程序崩溃,并需要更好的钩子管理。
我真的很喜欢这个聪明的机制,并希望有人能了解一些。