初识反调试

1. IsDebuggerPresent()函数

包含在debugapi.h头文件中,函数原型:

1
BOOL IsDebuggerPresent();   //未在调试器中运行时返回值为零,否则为非零值

该函数允许程序确定是否正在调试它,以便可以修改其行为

2. PEB->BeingDebugged

FS标志段寄存器总是指向TEB(当前的线程环境块),其中包含一个指针指向当前PEB(进程环境块),该结构体包含一个成员BeingDebugged,它是一个标志位,用于标识当前进程是否正在被调试

3. NtQueryInformationProcess函数

包含在ntdll.h头文件中,语法如下:

1
2
3
4
5
6
7
__kernel_entry NTSTATUS NtQueryInformationProcess(
[in] HANDLE ProcessHandle,
[in] PROCESSINFOCLASS ProcessInformationClass,
[out] PVOID ProcessInformation,
[in] ULONG ProcessInformationLength,
[out, optional] PULONG ReturnLength
);

其检索一个WORD_PTR值,该值是进程的调试器端口号。非零值指示进程正在环3调试器的控制下运行,如果进程没有调试器,则返回零

4. EPROCESS_DebugPort

获取系统内核中标记进程信息的结构体EPROCESS,通过EPROCESS结构体中的DebugPort成员判断进程是否正在被调试,一般无法使用普通方法实现,需要内核调试

5. 异常处理检测

处理异常时,正常运行过程会将信息发给Windows的SEH异常捕获流程,而进行调试时则会发给调试器

6. 断点检测

函数断点体现为0xCC,可通过对比内存数据中的指令数据与磁盘内文件的数据进行对比,如发现存在不同,则说明有断点,即程序被调试

7. 检测调试器进程

通过枚举进程,判断进程名是否为调试器进程名,如果是,则说明程序正在被调试

还可通过查看是否存在调试器的窗口,判断程序是否正在被调试。可使用VC++中附带的Spy++查找窗口名

8. 时间检测

程序运行时,如果被调试,则由于会出现单步运行等过程,程序运行速度会变慢,因此可通过检测程序运行时间,判断程序是否正在被调试