BeingDebugged 标志位
一、通过检测 BeingDebugged 标志位
在调试过程中,当被调试进程被调试器附加后,被调试进程中的所有线程的 PEB
结构中的 BeingDebugged
位会被置为 1,因此我们可以通过检测该标志位来检测是否有调试器进行附加。
我们首先通过 windbg 软件来看一下这个标志位位于进程的哪个地方,我们首先通过 windbg 附加任意一个 32 位或 64 位程序,然后输入命令显示当前进程中的所有线程:
~
得到如下结果:
我们任选一个线程,然后查看它的 TEB
结构:
dt ntdll!_TEB 0x000000b3`1cf88000
结果如下:
我们可以从一个线程的 TEB
结构中偏移为 0x60 的位置找到其 PEB
结构地址,接下来继续通过命令来解析该线程的 PEB
:
dt ntdll!_PEB 0x000000b3`1cf87000
结果如下:
可以看到,BeingDebugged
标志位于 PEB
结构体中偏移为 0x2 的位置,事实上这个标志位在其他 Windows 版本的系统上也位于这个位置,很少变动,我们演示的进程为 64 位的,对于 32 位的进程也是同理。
1 通过 IsDebuggerPresent 函数来检测调试器
Windows 系统提供了一个 API 来专门对该标志位进行检测,那就是 IsDebuggerPresent
函数,我们来看一下这个函数的底层汇编实现,首先来看一下 32 位的系统是如何实现的。
我们通过 x64dbg 来加载一个 32 位的程序,并跳转到该函数的实现:
从上面的截图中我们可以得到一些信息,首先,这个 IsDebuggerPresent
函数位于 kernelbase.dll 中,其次,第一行汇编代码先从 fs:[30]
中取值,在 32 位程序中,fs
段寄存器保存的是当前线程的 TEB
地址,因此该汇编指令其实是直接取当前线程的 TEB
结构中偏移为 0x30 的值,这个值其实就是 32 位程序中的 PEB
结构地址,然后再通过 PEB
结构地址偏移 0x2,得到了 BeingDebugged
标志位并返回。
那么 64 位的程序呢?我们上面通过 windbg 分析过,64 位程序中,PEB
在 TEB
结构中偏移为 0x60 的位置,只不过 64 位程序中保存 TEB
结构地址的段寄存器为 gs
,我们用 x64dbg 随便打开一个 64 位程序进行验证:
分析完 IsDebuggerPresent
函数的原理后,我们可以直接编写 C 语言代码调用 API 函数进行检测,也可以自己编写汇编代码来进行检测,接下来我们以 C 语言代码来进行示范:
#include <stdio.h>
#include <Windows.h>
int main()
{
if (IsDebuggerPresent())
{
printf("检测到调试器\r\n");
}
else
{
printf("未检测到调试器\r\n");
}
system("pause");
}
用调试器打开该程序,结果如下: