2013-04-29 29 views
14

我正在做一个所谓的'嘘钩'。实际上它改变了内存区域的权限,并在访问时捕获异常,因此可以挂钩该功能。设置单步陷阱可用赢7?

它采用了单步陷阱,看起来像:

info->ContextRecord->EFlags |= 0x100; 

恢复保护PAGE_NOACCESS

该应用程序在win xp上运行良好,但不像win 7那样运行得很好。它在win 7上刚被冻结。我非常怀疑这是因为'设置单步陷阱'的原因,但我不确定。

Click here到源包的直接下载链接

+3

只需按正常方式挂接该功能即可。这些疯狂的技术很可能会将您的代码标记为恶意软件。 – 2013-05-07 19:38:53

+0

你是否以管理员身份启动该程序? Windows 7为程序权限添加了安全级别烦恼级别。您可以通过设置链接器 - >清单文件 - > UAC执行级别 - > requireAdmin – typ1232 2013-05-08 15:55:32

回答

11

短的答案:

是单步标志是x86 achitecture的一部分,并且还仍然在视窗7经由处理器的EFLAGS组件实现上下文。

我设法下载你的项目,一切工作正常,无需在UAC关闭的Windows 8上修改。所以它也可以在Windows 7上运行。当启动VEH Hooking Test.exe它显示两个消息框,每获得一个MessageBoxA控制台输出后,所以钩子工作。也许尝试在Windows 7上以管理员身份启动该程序?


龙答:

SEH代表结构化异常处理,但你所描述听起来更像VEH - 向量异常处理。

VEH挂钩是一种非常慢的挂钩方法,因此它不能真正用于性能关键的挂钩,例如图形挂钩,例如您的挂钩每秒触及多次。它通常用于一次性挂钩。 VEH挂钩的目的是非常隐蔽。在别人的代码中没有写入内存,您不必使用调试寄存器。


以下是我将如何使用C++实现它。

首先你必须注册一个向量的异常处理程序。这是该进程的全局异常处理程序。每个抛出的未处理异常都会被这个处理程序捕获。

PVOID pExHandler = AddVectoredExceptionHandler(1, VectoredHandler); 

之后,你应该设置页面,在这里您HOOK_LOCATION(地址挂钩)的内存保护是我使用新的保护是PAGE_EXECUTE_READ|PAGE_GUARD。保护页面会导致访问异常,并在此后自动移除防护保护。这个异常不会被任何人处理,所以它会落入我们的向导处理程序。抛出异常之后,页面可以再次访问。 (请参阅Creating Guard Pages

内存只能在页面中保护(通常为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; 
} 

如果代码运行到受保护的内存页面,它会抛出守卫页违规。我们检查我们是否在挂钩位置。如果我们是一切都很好,我们可以调用钩子回调。如果我们不在正确的位置,我们需要重新保护代码,但是如果我们现在要做,我们就无法前进,并且始终在同一位置发生异常并导致应用程序死锁。所以我们设置处理器单步标志。

现在当接收到单步异常时,我们可以重新设置防护保护,因为我们是通过一条指令来进行的。这就是我们可以始终保护目标页面并且不会错过任何钩子命中的原因。

成本是在目标页面中执行的每条指令的两个例外和一个页面保护。不要试图用附加的调试器来做到这一点。它会发疯。

对于一个实际的实现,你可能需要同步对象来摆脱钩子而不会崩溃程序和更好的挂钩管理。

我真的很喜欢这个聪明的机制,并希望有些人了解一点。

+0

来请求权限。我不确定这是否回答OP问题,但感谢您的解释,我喜欢读它! – 2013-05-08 15:38:39

+0

@ dema80感谢您的反馈。我实际上设法猜测现在在哪里下载文件。一切工作正常我在Windows 6.x – typ1232 2013-05-08 15:52:43

+0

@ typ1232我修改了我的问题,添加一个直接下载链接到源,抱歉给您带来不便 – 2013-05-09 01:51:36