【问题标题】:Understanding some Antidebug inline asm for Windows / MSVC in C/C++了解 C/C++ 中 Windows / MSVC 的一些 Antidebug 内联汇编
【发布时间】:2019-02-04 20:22:39
【问题描述】:

我正在尝试了解https://github.com/nemesisqp/al-khaser/blob/0f74c40dde8ba060807e031271f81457a187fa08/DebuggerDetection.cpp#L603中的一些反调试器功能


__asm {
    mov eax, fs:[30h]
    mov al, [eax + 2h]
    mov IsDbg, al
}

功能相同

__asm mov IsDbg, [fs:[0x30] + 0x2]

如果没有,为什么不呢?

另外,如何将其转换为纯 C/C++?如何获取线程信息(特别是 fs:[30h])?


并且会

BOOL Int2DCheck()
{
    // The Int2DCheck function will check to see if a debugger
    // is attached to the current process. It does this by setting up
    // SEH and using the Int 2D instruction which will only cause an
    // exception if there is no debugger. Also when used in OllyDBG
    // it will skip a byte in the disassembly and will create

    __try
    {
        __asm
        {
            int 2dh
            xor eax, eax
            add eax, 2
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        return false;
    }

    return true;
}

__try
{
    __asm
    {
        xor eax, eax
        int 0x2d
        inc eax
    }
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
    return false;
}

如果没有,为什么不呢?

【问题讨论】:

  • mov IsDbg, [fs:[0x30] + 0x2] 有 2 个内存操作数,因此不可编码。源寻址模式也是不可编码的; x86 机器代码没有双重间接寻址模式。 (x86 asm 只是 x86 机器码的文本表示,因此每条指令都可以汇编成一条机器指令。)
  • 好的@PeterCordes,关于mov al, [ eax + 2h ]\nmov bDebuggerPresence, al,它会像mov bDebuggerPresence, [ eax + 2h ]一样工作吗?其他int 0x2d op 会在发布的 c/c++ 中工作吗?
  • 不,int 0x2d 是一个系统调用(但您尚未为其设置输入寄存器,因此没有更多上下文作为 sn-p 毫无意义)。 felixcloutier.com/x86/INTn:INTO:INT3:INT1.html。您在 Windows 上,因此 int ?? 系统调用 ABI 不稳定或没有正式记录,并且可能会随着更新/服务包而改变。
  • @Steve 它是反调试的东西,所以我不能完全测试它并确定它有效。
  • @PeterCordes 这就是我所拥有的所有上下文。 github.com/nemesisqp/al-khaser/blob/…

标签: c++ windows assembly x86 reverse-engineering


【解决方案1】:

这两种技术都比较古老。我认为它们在 2000 年代初(如果不是 90 年代后期的话)就已经在使用了。


第一个使用 Thread-Information Block (TIB) 驻留在 fs:[0] 的事实用于 Windows 进程(至少在 WinXP 之后...我从那时起就没有看过)。

TIB 中的偏移量 0x30 是指向 Process Environment Block (PEB) 的指针。从该链接中,我们看到 PEB 中的偏移量 0x2 是“正在调试”标志。这是 API 调用 IsDebuggerPresent 读取的值。


第二个例子演示了两种检测机制:

This answer 详细介绍了 int 0x2d 在 Windows 上的功能。目前,我们只注意到它是 Windows 内置调试​​支持的一部分。

更简单的机制是这样的:Windows 中的结构化异常处理会捕获基于语言的异常无法捕获的东西,因为它与操作系统的异常处理框架挂钩,而不是语言运行时的。

所以int 0x2d 会产生故障;存在的任何调试器都将处理该故障,并且由于此中断用于调试,因此调试器将照常返回控制流。因此,不会调用结构化异常处理机制......因此永远不会达到“捕获”,并且函数的返回值将因此改变。后来的 SEH 感知调试器通过告诉调试器将异常传递给程序,在这种情况下 SEH 会触发,从而轻松地击败了这种方法。

另一种机制基于 int 0x2d 由 windows 处理的方式的细节,显然 OllyDbg (一个曾经非常出色的调试器,已经不复存在并返回充满恶意软件)没有完美地模拟。我个人不熟悉这种方法,所以我会引导你到链接的答案。

就上下文而言,反调试器技术的早期研究是对特别流行的调试工具的研究。无论您从哪个文档中挖掘出这些技术,毫无疑问,您还会看到专门用于检测 NuMega Softice 的文档——可能是第一个用于 Windows(大约 NT 4.0)的内核调试器。派生我的句柄的指令序列被用作检测此调试器的方法。

感谢您的记忆之旅;)

【讨论】:

  • 这 (github.com/LordNoteworthy/al-khaser/blob/…) 与问题中的示例有何不同?
  • 类似机制:该代码不是使用 MSVC 的 __try/__except 语法自动执行此操作,而是使用 WinAPI 调用手动构建 SEH 链。请注意,该函数将标志 'swallowedException` 设置为 true,如果触发,处理函数将其设置回 false。 “向量异常”是 SEH 的扩展。
  • 所以澄清一下,将 swalledException 设置为 false 的处理程序意味着存在调试器?
  • 不,相反。如果存在调试器,则调试器会吞下异常,因此处理程序永远不会触发。
  • 啊!现在它是有道理的。我想知道为什么您将其默认为 true :p 感谢您的帮助!可以问一下你是在哪里学的吗?我对这样的话题真的很感兴趣,我在大四开始攻读计算机科学学位,到目前为止还没有学到这样/有趣的东西:/
猜你喜欢
  • 1970-01-01
  • 2013-11-26
  • 2017-11-01
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
相关资源
最近更新 更多