来自群友:
芯
的投稿。
实验环境
- Windows 11 22H2 x64
- Visual Studio 2022 (安装了C 桌面开发组件)
- WinDbg Preview
- 备注:这个是笔者的实验环境,实际对于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 资料有了,直接上演示: