一、异常
1. SEH
2. SetUnhandledExceptionFilter()
- 进程中发生异常,若SEH未处理或者注册的SEH不存在,此时会调用执行系统的kernel32!UnhandledExceptionFilter()API.该函数内部会运行系统的最后一个异常处理器(名为Top Level Exception Filter或Last Exception Filter).系统最后的异常处理器通常会弹出错误消息框,然后终止进程运行。
- kernel32!UnhandledExceptionFilter()API内部调用了ntdll!NtQueryInformationProcess(ProcessDebugPort)这个API(静态反调试),来判断是否正在调试进程。若进程正常运行(非调试状态),则运行系统最后的异常处理器,否则将异常派送给调试器。通过kernel32!SetUnhandledExceptionFilter可以修改系统最后的异常处理器。
- 基于异常的反调试技术中,通常先故意触发异常,然后在新注册的Last Exception Filter内部判断进程是正常运行还是调试运行,并根据判断结果修改EIP。
二、Timing Check
- 在调试器中逐行跟踪代码比程序正常运行耗费的时间要长很多,Timing Check技术通过计算运行的时间差异来判断进程是否处于被调试状态。
1.时间间隔测量
测量时间间隔的方法有很多,例如
基于计数器
RDTSC (汇编指令)
kernel32!QueryPerformanceCounter() / ntdll!NtQueryPerformanceCounter()
kernel32!GetTickCount()
基于时间
timeGetTime()
__ftime()
计数器的精准程度从高到低:
RDTSC>NtQueryPerformanceCounter()>GetTickCount()
2.RDTSC
x64CPU中存在一个名为TSC(Time Stamp Counter时间戳计数器)的64位寄存器。RDTSC这个汇编指令将TSC值读入EDX:EAX寄存器(高32位被保存到EDX,低32位被保存到EAX)
三、陷阱标志
- 陷阱标志指EFLAGS寄存器的第九个(Index 8)比特位, Trap Flag,(在x64dbg中表示为TF)
- TF设置为1后,CPU将进入单步执行模式。单步执行模式中,CPU执行1条指令后即触发EXCEPTION_SINGLE_STEP异常,然后TF会自动清零(0)。
INT 2D
- 在调试模式下执行完INT 2D后,下一条指令的第一个字节将被调试器忽略。(od的bug?)(若设置TF为1后再执行INT 2D,则不会忽略)