跳转到内容

x86 反汇编/调试器检测

来自维基教科书,开放的书籍,为开放的世界

检测调试器

[编辑 | 编辑源代码]

您可能会惊讶地发现,正在运行的程序实际上可以检测到附加的用户模式调试器。此外,也存在检测内核模式调试器的方法,尽管使用的方法在很大程度上取决于试图检测的调试器。

本主题与本书的叙述无关,大多数读者可以将本节视为可选内容。

IsDebuggerPresent API

[编辑 | 编辑源代码]

Win32 API 包含一个名为“IsDebuggerPresent”的函数,如果程序正在被调试,它将返回布尔值 true。以下代码片段将详细说明此函数的一般用法

 if(IsDebuggerPresent())
 {
   TerminateProcess(GetCurrentProcess(), 1);
 }

当然,在反汇编代码中很容易发现 IsDebuggerPresent() 函数的用法,并且熟练的逆向工程人员只需修补代码以删除此行。对于 OllyDbg,有很多可用的插件可以隐藏调试器,使其无法被此 API 和许多其他 API 检测到。

PEB 调试器检查

[编辑 | 编辑源代码]

进程环境块存储 IsDebuggerPresent 查询以确定其返回值的值。为了避免怀疑,一些程序员直接从 PEB 访问该值,而不是调用 API 函数。以下代码片段显示了如何访问该值

mov eax, [fs:0x30] 
mov al, [eax+2] 
test al, al 
jne @DebuggerDetected

内核模式调试器检查

[编辑 | 编辑源代码]

在 Windows 32 位和 64 位 Win <XP?, 7, 8.1 和 10 上。

有一个名为 _KUSER_SHARED_DATA 的结构,它在偏移量 0x2D4 处包含一个名为 'KdDebuggerEnabled' 的字段,如果 KDM 处于活动状态,则将其设置为 0x03,否则设置为 0x00。

该结构的基地址在不同的 Windows 版本中是静态的(0x7FFE0000),即使 < XP 也是如此。

该字段由内核不断更新,最后两位设置为 '11'。

以下汇编指令将在 32 位和 64 位应用程序中都能正常工作

cmp byte ptr ds:[7FFE02D4], 3
je @DebuggerDetected

这有很多优点。 已知的资料来源。

调试器可以在代码中设置断点,因此可以停止程序执行。程序可以通过监控系统时钟来检测到这一点。如果指令之间经过的时间过长,则可以确定程序被停止并正在进行分析(尽管并非总是如此)。如果程序花费的时间过长,则程序可以终止。

请注意,在抢占式多线程系统(例如现代 Windows 或 Linux 系统)中,系统会从您的程序切换到运行其他程序。这称为线程切换。如果系统有许多线程要运行,或者某些线程占用处理器时间过长,您的程序可能会检测到长时间延迟,并错误地确定程序正在被调试。

检测 SoftICE

[编辑 | 编辑源代码]

SoftICE 是一种本地内核调试器,因此,它不像用户模式调试器那样容易检测到。IsDebuggerPresent API 函数无法检测到 SoftICE 的存在。

要检测 SoftICE,可以使用多种技术

  1. 搜索 SoftICE 安装目录。如果安装了 SoftICE,则用户可能是黑客或逆向工程人员。
  2. 检测 int 1 的存在。SoftICE 使用中断 1 进行调试,因此,如果安装了中断 1,则 SoftICE 正在运行。


检测 OllyDbg

[编辑 | 编辑源代码]

OllyDbg 是一款流行的 32 位用户模式调试器。不幸的是,最近的几个版本(包括最新版本(v1.10))在处理 Win32 API 函数 OutputDebugString() 时存在漏洞。 [1] 试图阻止其程序被 OllyDbg 调试的程序员可以利用此漏洞使调试器崩溃。作者从未发布过修复程序,但有非官方版本和插件可用于保护 OllyDbg 免受利用此漏洞的攻击。

华夏公益教科书