一、異常
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,則不會忽略)
四、0xCC探測
API斷點0xCC檢測
五、比較校驗和