程序比较 正常启动和调试启动的 的某些初始信息的不同。从而实现判断程序是否 被调试
利用 fs 段寄存器指向的 TEB结构可以得到PEB结构体地址
move EAX, DWORD PTR FS:[0x30]
EAX → PEB结构的其实位置
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()
进行检测。
NtGlobalFlag 标志位
进程堆内存特征。调试和非调试值不一样。
调试时标志位的值 会被设置成 0→0x70
NtQueryInformationProcess() API 函数。
这个函数的第二个参数 为 7 或 0x1E 分别对应 ProcessDebugPort
ProcessDebugObjectHandle
当第二个 参数 为7 回返回 调试端口的值, 正常为 0 ,调试为 0xffffffff
CheckRemoteDebuggerPresent()
内部调用了 ****第二个参数为 7 时 的 NtQueryInformationProcess()。
当第二个 参数 为0x1E 时 正常返回0,调试返回 非0
STARTUPINFO
程序正常启动的时候 利用 CreateProcess()
函数创建进程启动
正常启动 会把 这个函数里面 的 STARTUPINFO 结构体的值设置为0 ,调试启动不会被设置为0。
SedebugPrivilege调试权限
程序正常启动 不会 具备这个权限。系统启动的时候会启动一个核心进程csrss.exe,我们可以通过判断能否使用OpenProcess打开该进程来检查当前进程是否具有调试权限。有管理员权限和调试权限才嫩打开这个 csrss.exe
注册表检测
当程序利用调试器时,程序的注册表中的 JIT 值会被修改我们可以检查注册表里面是否有对应字符串。
解决 把 对应的字符串 修改为 0
窗口检测
FindWindow
、EnumWindows
这两个函数 可以得到窗口的句柄。 判断窗口名称是否时对应的 字符串。
解决 把 对应的字符串 修改为 0
父进程检测
正常启动 父进程为 **exeplorer.exe 。**调试启动 父进程为 调试器。
利用 NtQueryInformationProcess
获得父进程的 PID
可能只检查程序的父进程名字,可以把调试器名字改为 exeplorer.exe
进程扫描
暴力查抄 是不是又敏感 进程。
内核对象扫描
调试对象创建时 DebugObject 类型的内核对象会被创建。遍历内核对象能够判断。
调试模式检测
判断调试的环境是不是调试模式
调试器攻击
里面ZwSetInformationThread()
函数传参ThreadHideFromDebugger
时,如果不是正常运行,这个函数会让当前线程(一般是主线程)脱离调试器,使调试器无法继续接收该线程的调试事件
动态反调试手段:调试行为检测,动态反调试的主要目的是干扰调试器,使其无法正常跟踪程序的执行流程或加大其逆向分析难度。