来自群友:的投稿。

实验环境

  • Windows 11 22H2 x64
    System.png
  • Visual Studio 2022 (安装了C++桌面开发组件)
    IDE.png
  • WinDbg Preview
    Windbg.png
  • 备注:这个是笔者的实验环境,实际对于Windows Vista 以上的操作系统都基本适用(对系统有更高要求的会另行说明)
  • 本教程源代码下载地址

github.com/ProgrammerCenter/Simple_Guide_Of_Windows_AntiDebug_In_User_Mode

方式1:PEB检测

Windows 下记录有两个记录进程信息和线程信息的结构 TEB/PEB
这两个结构很复杂,我们只关注PEB的BeingDebugged的标志
检测很简单,微软提供了一个API,叫IsDebuggerPresent
照着文档用就行
下面是一个简单的测试:

这里笔者使用了Windbg和Visual Studio内置的调试器,都可以正常识别
其实Windows在PEB的BeingDebugged标志为TRUE之后,还有别的操作,鉴于笔者没有具体研究过这些变化,故这里不再深入(有时间可以单独补一篇)

方式2:线程隐藏调试

从Windows 2000开始,微软在一个内部函数上提供了这个功能
其效果是:对指定设置了隐藏调试的线程,打断点,断点不断,且程序会退出
原理是:Windows对设置了线程隐藏调试的线程,出现异常不会通知调试器,又因为异常没有处理,会直接终止进程
(说明:软硬件断点触发的方式都是引发异常,尤其软件断点,是写入int 3指令,其执行时会抛出一个0x00000003的异常)
使用方法:调用NtSetInformationThread,其调用语句是:NtSetInformationThread(线程句柄,0x11,0,0);
由于微软官方文档没有讲到这种用法,我这里不贴官方文档了,具体可自行百度
下面是演示:

方法3:(核弹级别)Hook DbgUiRemoteBreakin (让调试器一附加就退出的流泪神器)

为啥有这么一招,这还要说说Windows调试器是如何在附加时让被调试器断下来的
原理太简单了:创建一个远程线程,执行DbgUiRemoteBreakin,DbgUiRemoteBreakin内部触发int 3断点,这是Windows必做操作
所以,直接Hook它,然后ExitProcess,这不就一附加就退了
不过各位观众老爷可能需要一点汇编基础(不会也没关系)大家可以搜索Windows32/64位inline hook获取相关资料
这里贴一个网址inline hook
知道这里,其实就是覆盖Windows的原代码,跳转到我们的函数,直接ExitProcess即可(不需要回去)
下面是演示:

方法4:自调试

Windows只允许一个被调试进程被一个调试进程调试,利用这一点,直接自己调试自己不香(注意不能直接自己调试自己,会用到双进程)
放一下微软的调试API,我们便是使用它
Mircosoft Debug API for Windows
资料有了,直接上演示:

最后修改:2022 年 10 月 14 日
如果觉得我的文章对你有用,请随意赞赏