【问题标题】:Is set single step trap available on win 7?win 7可以设置单步陷阱吗?
【发布时间】:2013-04-22 17:12:11
【问题描述】:

我正在使用所谓的“seh hooking”。实际上它改变了内存区域的权限并在访问时捕获了异常,因此它可以挂钩该函数。

它使用单步陷阱,如下所示:

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

恢复对PAGE_NOACCESS的保护。

该应用程序在 win xp 上运行良好,但在 win 7 上却没有例外。它在 win 7 上被冻结。我非常怀疑这是因为“设置单步陷阱”的事情,但我不确定。

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

【问题讨论】:

  • 按正常方式挂钩函数即可。这些疯狂的技术很可能会将您的代码标记为恶意软件。
  • 您是否以管理员身份启动该程序? Windows 7 为程序权限增加了一个安全级别。您可以通过设置 Linker->Manifest File->UAC execution level->requireAdmin 请求权限

标签: c++ windows winapi visual-c++ hook


【解决方案1】:

简答:

是的,单步标志是 x86 架构的一部分,并且仍然通过处理器上下文的 eflags 组件在 Windows 7 中实现。

我已成功下载您的项目,并且在关闭 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;
}

如果代码运行到受保护的内存页面,它将引发保护页面冲突。我们检查我们是否在钩子位置。如果我们一切都很好,我们可以调用钩子回调。如果我们不在正确的位置,我们需要以某种方式重新保护代码,但如果我们现在就这样做,我们就无法前进并且总是在同一位置获得异常并死锁应用程序。所以我们设置处理器单步标志。

现在当收到单步异常时,我们可以再次设置保护保护,因为我们前进了一条指令。这就是我们如何始终保护目标页面而不会错过任何钩子命中的方法。

成本是在目标页面中执行的每条指令有两个例外和一个页面保护。不要尝试在附加调试器的情况下执行此操作。会发疯的。

对于实际实现,您可能需要同步对象来摆脱钩子而不会使程序崩溃并更好地管理钩子。

我真的很喜欢这种巧妙的机制,希望有人能从中有所了解。

【讨论】:

  • 我不确定这是否能回答 OP 问题,但感谢您的解释,我喜欢阅读!
  • @dema80 感谢您的反馈。我实际上设法猜测现在在哪里下载文件。在 Windows 6.x 上一切正常
  • @typ1232 我已经修改了我的问题,添加了直接下载到源的链接,不便之处敬请见谅
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多