对于检测调试器来说,其实 Win32 API 中有现成的 IsDebuggerPresent 可以使用,不过调试器可以很容易地挂钩这个 API,使得被调试的进程检测调试器失败。
这里给出一段简单的代码,比 IsDebuggerPresent 更保险些:
C++代码
- #include <stdio.h>
- #include <excpt.h>
- int main(void)
- {
- __try
- {
- __asm int 3;
- puts("Debugger detected!");
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- puts("I'm ok!");
- }
- return 0;
- }
原理很简单,也就是利用了 Win32 的异常处理机制:当 __try 块中的 int 3 执行后,会触发内核的 KiTrap03 例程,这时如果有调试器的存在,那么 int 3 下面的代码就会被调试器执行;如果没有调试器的存在,那么代码将会跳至 __except 块中执行。
当然,对抗这一段代码的方式也很简单,只需要在调试器的设置中把 int 3 的异常过滤掉,也就是直接传递给应用程序即可。