静态反调试技术

一. 进程状态检查。

程序比较 正常启动调试启动的 的某些初始信息的不同。从而实现判断程序是否 被调试

利用 fs 段寄存器指向的 TEB结构可以得到PEB结构体地址 move EAX, DWORD PTR FS:[0x30] EAX → PEB结构的其实位置

  1. BeingDebugged 标志位

    在 32 PED 结构中,偏移为 0x02 的地方是一个**BeingDebugged** 标志位标志是否被调试状态

    如果是调试状态 标志位 0→1

    bool CheckDebug(){
    	bool bDebugged = falss;
    	__asm{
    		MOV EAX, DWORD PTR FS:[0x30]
    		MOV AL, BYTE PTR DS:[EAX + 2]
    		MOV bDebugged, AL
    	}
    	return bDebugged;
    }
    

    可以利用 API 函数 IsDebuggerPresent() 进行检测。

  2. NtGlobalFlag 标志位

    进程堆内存特征。调试和非调试值不一样。

    调试时标志位的值 会被设置成 0→0x70

  3. NtQueryInformationProcess() API 函数。

    这个函数的第二个参数 为 7 或 0x1E 分别对应 ProcessDebugPort ProcessDebugObjectHandle

  4. STARTUPINFO

    程序正常启动的时候 利用 CreateProcess() 函数创建进程启动

    正常启动 会把 这个函数里面 的 STARTUPINFO 结构体的值设置为0 ,调试启动不会被设置为0。

  5. SedebugPrivilege调试权限

    程序正常启动 不会 具备这个权限。系统启动的时候会启动一个核心进程csrss.exe,我们可以通过判断能否使用OpenProcess打开该进程来检查当前进程是否具有调试权限。有管理员权限和调试权限才嫩打开这个 csrss.exe

二. 调试环境检测

  1. 注册表检测

    当程序利用调试器时,程序的注册表中的 JIT 值会被修改我们可以检查注册表里面是否有对应字符串。

    解决 把 对应的字符串 修改为 0

  2. 窗口检测

    FindWindowEnumWindows 这两个函数 可以得到窗口的句柄。 判断窗口名称是否时对应的 字符串。

    解决 把 对应的字符串 修改为 0

  3. 父进程检测

    正常启动 父进程为 **exeplorer.exe 。**调试启动 父进程为 调试器。

    利用 NtQueryInformationProcess 获得父进程的 PID

    可能只检查程序的父进程名字,可以把调试器名字改为 exeplorer.exe

  4. 进程扫描

    暴力查抄 是不是又敏感 进程。

  5. 内核对象扫描

    调试对象创建时 DebugObject 类型的内核对象会被创建。遍历内核对象能够判断。

  6. 调试模式检测

    判断调试的环境是不是调试模式

  7. 调试器攻击

    里面ZwSetInformationThread()函数传参ThreadHideFromDebugger 时,如果不是正常运行,这个函数会让当前线程(一般是主线程)脱离调试器,使调试器无法继续接收该线程的调试事件

三.动态反调试技术。

动态反调试手段:调试行为检测,动态反调试的主要目的是干扰调试器,使其无法正常跟踪程序的执行流程或加大其逆向分析难度。

(1) 时钟检测。