NtGlobalFlag
在 32 位机器上,NtGlobalFlag 字段位于PEB (进程环境块)0x68 的偏移处,64 位机器则是在偏移0xBC 位置。该字段的默认值为 0。当调试器正在运行时,该字段会被设置为一个特定的值(0x70,FLG_HEAP_ENABLE_TAIL_CHECK (0x10) |
FLG_HEAP_ENABLE_FREE_CHECK (0x20) | FLG_HEAP_VALIDATE_PARAMETERS (0x40))。 |
1 |
|
Ollydbg对cmp前设置设置断点,运行程序触发断点。然后打开CommandLine
插件用dump fs:[30]+0x68
dump 出NtGlobalFlag
的内容,右键选择Binary->Fill with 00's
将值0x70
替换为0x00
即可。
IsDebuggerPresent
这个函数只是单纯地返回了BeingDebugged
标志的值(非0存在调试)。检查BeingDebugged
标志位的方法也可以用以下 代码实现,绕过方法:只需要将BeingDebugged
标志设为0
即可。
#32位代码检查32位环境
mov eax, fs:[30h] ;Process Environment Block
cmp b [eax+2], 0 ;check BeingDebugged
#64位代码检测64位环境
push 60h
pop rsi
gs:lodsq ;Process Environment Block
cmp b [rax+2], 0 ;check BeingDebugged
#32位代码检测64位环境
mov eax, fs:[30h] ;Process Environment Block
cmp b [eax+1002h], 0 ;check BeingDebugged
CheckRemoteDebuggerPresent
1 |
|
如果调试器存在 (通常是检测自己是否正在被调试),该函数会将pbDebuggerPresent
指向的值设为0xffffffff
。CheckRemoteDebuggerPresent
内部其实是通过调用NtQueryInformationProcess
。
NtQueryInformationProcess
未公开的ntdll
的NtQueryInformationProcess()
函数接受一个信息类的参数用于查询。常用的查询信息类:
ProcessDebugPort(7)
,当进程正在被调试时,返回值为0xffffffff
ProcessDebugObjectHandle (0x1e)
,当进程正在被调试时,返回值为1ProcessDebugFlags (0x1f)
,当进程正在被调试时,返回值为0
ZwSetInformationThread
关键代码为ZwSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, 0, 0);
,如果处于调试状态,执行完该行代码,程序就会退出。第2个参数为 ThreadHideFromDebugger,其值为 0x11。调试执行到该函数时,若发现第 2 个参数值为 0x11,跳过或者将 0x11 修改为其他值即可。
时间差监测
通过两次GetTickCount()差值判断程序是否处于被调试状态
ProcmonDebugLogger
通过检测设备文件\\\\.\\Global\\ProcmonDebugLogger
来检测ProcessMonitor
检测VMware
如果程序在 VMware 内运行,程序使用In
指令通过0x5658
端口读取数据时, EBX
寄存器的值就会变为0x564D5868
(0x564D5868 == "VMXh"
)
.text:0040127D mov eax, 564D5868h // <------VMXh
.text:00401282 mov ebx, 0
.text:00401287 mov ecx, 0Ah
.text:0040128C mov edx, 5658h // <------in 0x5658
.text:00401291 in eax, dx