如何检测当前.NET应用是否被非托管原生调试器附加调试?
C#检测第三方调试器附加的可行实现方案
以下方案均针对Windows 10环境设计,可检测x64dbg等逆向调试器的附加行为:
基础检测(仅适配常规VS调试,易绕过)
.NET框架自带的Debugger.IsAttached属性可以快速检测Visual Studio等官方调试器,但几乎所有逆向调试器都可以轻易绕过该检测,不建议单独使用。
方案1:调用Win32系统API CheckRemoteDebuggerPresent
该API由系统内核直接导出,检测可信度高于.NET自带属性,大部分未做对抗处理的调试器都会被命中,实现代码如下:
using System; using System.Diagnostics; using System.Runtime.InteropServices; public static partial class DebugDetector { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CheckRemoteDebuggerPresent(IntPtr hProcess, ref bool isDebuggerPresent); public static bool CheckByApi() { bool isDebugged = false; CheckRemoteDebuggerPresent(Process.GetCurrentProcess().Handle, ref isDebugged); return isDebugged; } }
方案2:直接读取进程PEB结构体的调试标识
该方案直接访问进程环境块(PEB)中的BeingDebugged标志,属于底层检测,可命中更多调整了API返回值的调试器,实现代码如下(需要开启项目的不安全代码编译选项):
public static partial class DebugDetector { [DllImport("ntdll.dll")] private static extern IntPtr NtCurrentTeb(); public static unsafe bool CheckByPebFlag() { IntPtr pebAddr; // 从TEB中获取PEB地址 if (Environment.Is64BitProcess) { pebAddr = *(IntPtr*)((byte*)NtCurrentTeb() + 0x60); } else { pebAddr = *(IntPtr*)((byte*)NtCurrentTeb() + 0x30); } // 读取PEB偏移0x2位置的BeingDebugged标志 return (*(byte*)((byte*)pebAddr + 0x2)) != 0; } }
补充增强方案
可以叠加以下检测逻辑提升对抗强度:
- 枚举系统运行进程,匹配已知调试器的进程名、签名特征
- 枚举顶层窗口,匹配已知调试器的窗口类名、窗口标题特征
- 加入时间差检测,单步调试会导致特定代码段的执行时间远超正常范围
注意:所有调试器检测逻辑都存在被绕过的可能,建议多层检测混合使用,检测命中后不要立刻触发退出逻辑,可选择延迟执行、抛出异常或者篡改程序运行结果,进一步提升逆向成本。
内容的提问来源于stack exchange,提问作者jimobo3865
相关产品推荐
相关产品推荐

