• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            軟件保護殼技術專題 - 反調試器技術

            Posted on 2009-10-14 15:13 S.l.e!ep.¢% 閱讀(1405) 評論(0)  編輯 收藏 引用 所屬分類: Crack
            玩命
            2008-08-21, 10:38
            反調試是軟件保護殼的最基本的功能之一。
            反調試方法也是多種多樣。通過調用標準的API接口,計算指令時間差。查看當調試器加載后的
            內存的一些標志,還有就是判斷當前運行環境是否合乎邏輯等方法。這里收集了一些反調試的方法,其中的命名規則使用了殼狼的反調試程序的方式,希望不要和我收取版權的費用。^_^,其中借鑒了不少殼狼的函數。增加了一些,也刪除了一些。大部分的參考資料來自<<脫殼的藝術>>,<<Anti-UnPacker Tricks>>與<<加密與解密第三版>>。
            這里要說明的一點是。每個函數編寫都是自己建立堆棧了,看的不習慣的多看下就習慣了 呵呵。
            原因也很簡單,MASM不允許在函數內定義函數了。
            這些函數還有一個要講的是。因為最后這些函數要在以后的章節中用到
            為了能允許用戶自定義反調試的功能。免去重定位的麻煩,所以
            利用棧傳遞了API集合地址和外部函數集合的地址。
            朋友們還是先看代碼了。。。


            利用IsDebuggerPresent確定是否存在,IsDebuggerPresent是WIN提供的一個標準調試API
            用于確定是否存在調試器。這個方法很簡單TRUE為存在,FASLE則為不存在。

            FD_IsDebuggerPresent:
            FD_IsDebugger_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FD_IsDebugger_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            call dword ptr [eax].xIsDebuggerPresent
            Exit_FD_IsDebuggerPresent:
            assume eax : nothing
            retn 04h
            End_FD_IsDebuggerPresent:
            我們更進一步的剖析IsDebuggerPresent函數,逆向它后即可得知。
            這個函數讀取當前進程的PEB中的BeingDebugger標志。
            如果確定這個標志呢?
            當進程加載的時候FS寄存器總是被設置成當前線程的TEB。這下就都OK
            而在TEB的30h偏移處就是ProcessEnvironmentBlock了。
            而PEB的偏移02h出就是BeingDebugged了。當BeingDebugger為0則沒有調試器
            不為0時則存在調試器。

            FD_PEB_BeingDebuggedFlag:
            assume fs : nothing
            mov eax, fs:[30h] ; eax = TEB.ProcessEnvironmentBlock
            inc eax
            inc eax
            mov eax, dword ptr [eax]
            and eax, 000000FFh ; al = PEB.BeingDebugged
            test eax, eax
            jnz FD_PEB_BeingDebuggedFlag_Found
            Exit_PEB_BeingDebuggedFlag:
            retn 0
            FD_PEB_BeingDebuggedFlag_Found:
            mov eax, 1
            jmp Exit_PEB_BeingDebuggedFlag
            End_FD_PEB_BeingDebuggedFlag:
            在當BeingDebugged被設置為TRUE時,存在與PEB中的
            NtGlobalFlag也會做出相應的改變。查看WIN2K代碼的LdrpInitialize
            會發現以下代碼
            if (Peb->BeingDebugged)
            Peb->NtGlobalFlag |= ***_HEAP_ENABLE_FREE_CHECK |
            ***_HEAP_ENABLE_TAIL_CHECK |
            ***_HEAP_VALIDATE_PARAMETERS;
            這個組合值為70h。所以我們又得到一個反調試的函數

            FD_PEB_NtGlobalFlags:
            assume fs : nothing
            mov eax, fs:[30h]
            mov eax, dword ptr [eax+68h]
            and eax, 070h
            test eax, eax
            jnz FD_PEB_NtGlobalFlags_Found
            Exit_FD_PEB_NtGlobalFlags:
            retn 0
            FD_PEB_NtGlobalFlags_Found:
            mov eax, 1
            jmp Exit_FD_PEB_NtGlobalFlags
            End_FD_PEB_NtGlobalFlags:
            BeingDebugger標志還會影響ProcessHeap.Flags
            如果這個標志不為0則存在調試器。

            FD_Heap_ForceFlags:
            assume fs : nothing
            mov eax, fs:[30h]
            mov eax, dword ptr [eax+18h] ; PEB.ProcessHeap
            mov eax, dword ptr [eax+10h] ; PEB.ProcessHeap.Flags
            test eax, eax
            jnz Found_FD_Heap_ForceFlags
            Exit_FD_Heap_ForceFlag:
            retn 0
            Found_FD_Heap_ForceFlags:
            mov eax, 1
            jmp Exit_FD_Heap_ForceFlag
            End_FD_Heap_ForceFlags:
            在BeingDebugger下ProcessHeap.ForceFlags也受到影響
            如果不為2則存在調試器。細節部分可以查看WIN2K的代碼。
            由于版本影響這里就不給出其中的代碼了。

            FD_Heap_HeapFlags:
            assume fs : nothing
            mov eax, fs:[30h]
            mov eax, dword ptr [eax+18h] ; PEB.ProcessHeap
            mov eax, dword ptr [eax+0ch] ; PEB.ProcessHeap.ForceFlags
            cmp eax, 2
            jnz Found_FD_Heap_HeapFlags
            Exit_FD_Heap_HeapFlags:
            retn 0
            Found_FD_Heap_HeapFlags:
            mov eax, 1
            jmp Exit_FD_Heap_HeapFlags
            End_FD_Heap_HeapFlags:
            通過另一個API。CheckRemoteDebuggerPresent,這個API可以檢測任何進程是否被調試器
            加載。這里通過GetCurrentProcess取得自身進程的句柄。進行鑒別

            FD_CheckRemoteDebuggerPresent:
            FD_CheckRemoteDebuggerPresent_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FD_CheckRemoteDebuggerPresent_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            push esp
            push esp
            call dword ptr [eax].xGetCurrentProcess
            push eax
            call dword ptr [eax].xCheckRemoteDebuggerPresent
            pop esp
            assume eax : nothing
            retn 04h
            End_FD_CheckRemoteDebuggerPresent:
            如果逆向了CheckRemoteDebuggerPresent函數就可以明白,其實最終它是調用
            NtQueryInformationProcess,查詢進程的ProcessDebugPort。此值是用來維持系統
            與調試器通訊的,在程序被調試器加載時系統會設置這個值為非0。

            FD_NtQueryInfoProc_DbgPort:
            FD_NtQueryInfoProc_DbgPort_Arg_Win32Api equ 08h
            FD_NtQueryInfoProc_DbgPort_StackSize equ sizeof PROCESS_DEBUG_PORT_INFO
            FD_NtQueryInfoProc_DbgPort_ProcessInfo equ -(FD_NtQueryInfoProc_DbgPort_StackSize)
            push ebp
            mov ebp, esp
            sub esp, FD_NtQueryInfoProc_DbgPort_StackSize

            push ebx

            mov ebx, dword ptr [ebp+FD_NtQueryInfoProc_DbgPort_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push NULL
            push sizeof PROCESS_DEBUG_PORT_INFO
            lea eax, [ebp+FD_NtQueryInfoProc_DbgPort_ProcessInfo]
            push eax
            push ProcessDebugPort
            call dword ptr [ebx].xGetCurrentProcess
            push eax
            call dword ptr [ebx].xZwQueryInformationProcess
            test eax, eax
            jnz FD_NtQueryInfoProc_DbgPort_Tmp1
            lea eax, [ebp+FD_NtQueryInfoProc_DbgPort_ProcessInfo]
            assume eax : ptr PROCESS_DEBUG_PORT_INFO
            mov eax, dword ptr [eax].DebugPort
            test eax, eax
            jnz Found_FD_NtQueryInfoProc_DbgPort
            FD_NtQueryInfoProc_DbgPort_Tmp1:
            xor eax, eax
            Exit_FD_NtQueryInfoProc_DbgPort:
            assume eax : nothing
            assume ebx : nothing

            pop ebx

            mov esp, ebp
            pop ebp
            retn 04h
            Found_FD_NtQueryInfoProc_DbgPort:
            mov eax, 1
            jmp Exit_FD_NtQueryInfoProc_DbgPort
            End_FD_NtQueryInfoProc_DbgPort:
            當Windows系統創建一個調試會話開始,一個調試對象也被創建并產生一個
            調試句柄。我們可以查詢這個句柄的值來確定是否存在調試器。

            FD_NtQueryInfoProc_DbgObjHandle:
            FD_NtQueryInfoProc_DbgObjHandle_Arg_Win32Api equ 08h
            FD_NtQueryInfoProc_DbgObjHandle_StackSize equ sizeof PROCESS_DEBUG_OBJECTHANDLE_INFO
            FD_NtQueryInfoProc_DbgObjHandle_ProcessInfo equ -(FD_NtQueryInfoProc_DbgObjHandle_StackSize)
            push ebp
            mov ebp, esp
            sub esp, FD_NtQueryInfoProc_DbgObjHandle_StackSize

            push ebx
            mov ebx, dword ptr [ebp+FD_NtQueryInfoProc_DbgObjHandle_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push NULL
            push sizeof PROCESS_DEBUG_OBJECTHANDLE_INFO
            lea eax, [ebp+FD_NtQueryInfoProc_DbgObjHandle_ProcessInfo]
            push eax
            push SystemNotImplemented8
            call dword ptr [ebx].xGetCurrentProcess
            push eax
            call dword ptr [ebx].xZwQueryInformationProcess
            test eax, eax
            jnz FD_NtQueryInfoProc_DbgObjHandle_Tmp1
            lea eax, [ebp+FD_NtQueryInfoProc_DbgObjHandle_ProcessInfo]
            assume eax : ptr PROCESS_DEBUG_OBJECTHANDLE_INFO
            mov eax, dword ptr [eax].ObjectHandle
            test eax, eax
            jnz Found_FD_NtQueryInfoProc_DbgObjHandle
            FD_NtQueryInfoProc_DbgObjHandle_Tmp1:
            xor eax, eax
            Exit_FD_NtQueryInfoProc_DbgObjHandle:

            assume eax : nothing
            assume ebx : nothing

            pop ebx

            mov esp, ebp
            pop ebp
            retn 04h
            Found_FD_NtQueryInfoProc_DbgObjHandle:
            mov eax, 1
            jmp Exit_FD_NtQueryInfoProc_DbgObjHandle
            End_FD_NtQueryInfoProc_DbgObjHandle:
            也可以通過使用ZwQueryInformationProcess函數,利用SystemNotImplemented9(1fh)
            返回的PROCESS_DEBUG_FLAGS_INFO結構,如果DebugFlags返回0則檢測到調試器。返回非0
            則沒發現調試器。

            FD_NtQueryInfoProc_DbgFlags:
            FD_NtQueryInfoProc_DbgFlags_Arg_Win32Api equ 08h
            FD_NtQueryInfoProc_DbgFlags_StackSize equ sizeof PROCESS_DEBUG_FLAGS_INFO
            FD_NtQueryInfoProc_DbgFlags_ProcessInfo equ -(FD_NtQueryInfoProc_DbgFlags_StackSize)
            push ebp
            mov ebp, esp
            sub esp, FD_NtQueryInfoProc_DbgFlags_StackSize

            push ebx

            mov ebx, dword ptr [ebp+FD_NtQueryInfoProc_DbgFlags_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push NULL
            push sizeof PROCESS_DEBUG_FLAGS_INFO
            lea eax, [ebp+FD_NtQueryInfoProc_DbgFlags_ProcessInfo]
            push eax
            push SystemNotImplemented9
            call dword ptr [ebx].xGetCurrentProcess
            push eax
            call dword ptr [ebx].xZwQueryInformationProcess
            test eax, eax
            jnz FD_NtQueryInfoProc_DbgFlags_Tmp1
            lea eax, [ebp+FD_NtQueryInfoProc_DbgFlags_ProcessInfo]
            assume eax : ptr PROCESS_DEBUG_FLAGS_INFO
            mov eax, dword ptr [eax].DebugFlags
            test eax, eax
            jz Found_FD_NtQueryInfoProc_DbgFlags
            FD_NtQueryInfoProc_DbgFlags_Tmp1:
            xor eax, eax
            Exit_FD_NtQueryInfoProc_DbgFlags:
            assume eax : nothing
            assume ebx : nothing

            pop ebx

            mov esp, ebp
            pop ebp
            retn 04h
            Found_FD_NtQueryInfoProc_DbgFlags:
            mov eax, 1
            jmp Exit_FD_NtQueryInfoProc_DbgFlags
            End_FD_NtQueryInfoProc_DbgFlags:
            如果Windows以調試方式啟動,并與系統調試器建立通訊。
            通過ZwQuerySystemInformation對SystemKernelDebuggerInformation進行查詢
            系統中是否存在系統調試器。

            FD_NtQueryInfoProc_SysKrlDbgInfo:
            FD_NtQueryInfoProc_SysKrlDbgInfo_Arg_Win32Api equ 08h
            FD_NtQueryInfoProc_SysKrlDbgInfo_StackSize equ sizeof PROCESS_DEBUG_FLAGS_INFO
            FD_NtQueryInfoProc_SysKrlDbgInfo_Info equ -(sizeof PROCESS_DEBUG_FLAGS_INFO)
            push ebp
            mov ebp, esp
            sub esp, FD_NtQueryInfoProc_SysKrlDbgInfo_StackSize

            push ebx

            mov ebx, dword ptr [ebp+FD_NtQueryInfoProc_SysKrlDbgInfo_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push NULL
            push sizeof PROCESS_DEBUG_FLAGS_INFO
            lea eax, [ebp+FD_NtQueryInfoProc_SysKrlDbgInfo_Info]
            push eax
            push SystemKernelDebuggerInformation
            call dword ptr [ebx].xGetCurrentProcess
            push eax
            call dword ptr [ebx].xZwQuerySystemInformation
            test eax, eax
            jnz FD_NtQueryInfoProc_SysKrlDbgInfo_Tmp1
            lea eax, [ebp+FD_NtQueryInfoProc_SysKrlDbgInfo_Info]
            assume eax : ptr PROCESS_DEBUG_FLAGS_INFO
            mov eax, dword ptr [eax].DebugFlags
            test eax, eax
            jz Found_FD_NtQueryInfoProc_SysKrlDbgInfo
            FD_NtQueryInfoProc_SysKrlDbgInfo_Tmp1:
            xor eax, eax
            Exit_FD_NtQueryInfoProc_SysKrlDbgInfo:
            assume eax : nothing
            assume ebx : nothing

            pop ebx

            mov esp, ebp
            pop ebp
            retn 04h
            Found_FD_NtQueryInfoProc_SysKrlDbgInfo:
            mov eax, 1
            jmp Exit_FD_NtQueryInfoProc_SysKrlDbgInfo
            End_FD_NtQueryInfoProc_SysKrlDbgInfo:
            當調試會話被創建,這個標志會影響堆的創建。初始化中的堆內存填充了
            很多類似0ABABABABh,0BAADF00Dh,0FEEEFEEEh這三個值。可以通過檢測內存看
            是否存在過多的這樣值。判斷調試器的存在,而正常啟動的程序則不會被填充。

            FD_Heap_Magic:
            FD_Heap_Magic_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FD_Heap_Magic_Arg_Win32Api]

            push ebx
            push ecx
            push edx
            push esi
            push edi

            mov ebx, eax
            assume ebx : ptr WIN32APIBASE

            push 100h
            push NULL
            call dword ptr [ebx].xGetProcessHeap
            mov edi, eax ; HeapHandle
            push eax
            call dword ptr [ebx].xHeapAlloc
            mov esi, eax ; HeapMem
            xor ecx, ecx
            mov edx, 100h
            cld
            FD_Heap_Magic_Loop:
            lodsd
            cmp eax, 0ABABABABh
            jnz FD_Heap_Magic_Tmp1
            inc ecx
            FD_Heap_Magic_Tmp1:
            cmp eax, 0BAADF00Dh
            jnz FD_Heap_Magic_Tmp2
            inc ecx
            FD_Heap_Magic_Tmp2:
            cmp eax, 0FEEEFEEEh
            jnz FD_Heap_Magic_Tmp3
            inc ecx
            FD_Heap_Magic_Tmp3:
            sub edx, 04h
            jnz FD_Heap_Magic_Loop
            push ecx
            ;; free heap
            push esi
            push HEAP_NO_SERIALIZE
            push edi
            call dword ptr [ebx].xHeapFree
            pop ecx
            ;; judge count
            cmp ecx, 10h
            jae Found_FD_Heap_Magic
            xor eax, eax
            Exit_FD_Heap_Magic:
            pop edi
            pop esi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            retn 04h
            Found_FD_Heap_Magic:
            mov eax, 1
            jmp Exit_FD_Heap_Magic
            End_FD_Heap_Magic:
            一般程序是沒有被設置SeDebugPrivilege,如果一個當前進程被設置SeDebugPrivilege后
            它就擁有了完全控制CSRSS.EXE的權限。通過進程表快照取得CSRSS.EXE進程的PID,之后
            通過OpenProcess以PROCESS_ALL_ACCESS打開。開是否能打開此進程。

            FD_SeDebugPrivilege:
            FD_SeDebugPrivilege_Arg_Win32Api equ 08h
            FD_SeDebugPrivilege_StackSize equ 10h + sizeof PROCESSENTRY32
            FD_SeDebugPrivilege_hProcessSnap equ -04h
            FD_SeDebugPrivilege_PID_csrss equ -08h
            FD_SeDebugPrivilege_FingFlag equ -0ch
            FD_SeDebugPrivilege_pe32 equ -(10h+sizeof PROCESSENTRY32)
            push ebp
            mov ebp, esp
            sub esp, FD_SeDebugPrivilege_StackSize

            push ebx
            push ecx
            push edi

            ;; clear stack
            lea edi, [ebp-FD_SeDebugPrivilege_StackSize]
            mov ecx, FD_SeDebugPrivilege_StackSize
            xor eax, eax
            cld
            rep stosb

            mov ebx, dword ptr [ebp+FD_SeDebugPrivilege_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            lea edi, [ebp+FD_SeDebugPrivilege_pe32]
            assume edi : ptr PROCESSENTRY32

            push 0
            push TH32CS_SNAPPROCESS
            call dword ptr [ebx].xCreateToolhelp32Snapshot
            cmp eax, INVALID_HANDLE_VALUE
            jz NotFound_FD_SeDebugPrivilege
            mov dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap], eax
            push sizeof PROCESSENTRY32
            pop dword ptr [edi].dwSize

            push edi
            push dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap]
            call dword ptr [ebx].xProcess32First
            test eax, eax
            jnz FD_SeDebugPrivilege_Loop
            push dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap]
            call dword ptr [ebx].xCloseHandle
            jmp NotFound_FD_SeDebugPrivilege

            FD_SeDebugPrivilege_Loop:
            call FD_SeDebugPrivilege_Str
            db 'CSRSS.EXE',0
            FD_SeDebugPrivilege_Str:
            lea eax, [edi].szExeFile
            push eax
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jnz FD_SeDebugPrivilege_Tmp2
            push dword ptr [edi].th32ProcessID
            pop dword ptr [ebp+FD_SeDebugPrivilege_PID_csrss]
            push TRUE
            pop dword ptr [ebp+FD_SeDebugPrivilege_FingFlag]
            FD_SeDebugPrivilege_Tmp2:
            mov eax, dword ptr [ebp+FD_SeDebugPrivilege_FingFlag]
            test eax, eax
            jnz FD_SeDebugPrivilege_Tmp3
            push edi
            push dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap]
            call dword ptr [ebx].xProcess32Next
            test eax, eax
            jnz FD_SeDebugPrivilege_Loop

            FD_SeDebugPrivilege_Tmp3:
            mov eax, dword ptr [ebp+FD_SeDebugPrivilege_FingFlag]
            test eax, eax
            jz FD_SeDebugPrivilege_Tmp4
            push dword ptr [ebp+FD_SeDebugPrivilege_PID_csrss]
            push FALSE
            push PROCESS_QUERY_INFORMATION
            call dword ptr [ebx].xOpenProcess
            test eax, eax
            jz FD_SeDebugPrivilege_Tmp4
            push dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap]
            call dword ptr [ebx].xCloseHandle
            jmp Found_FD_SeDebugPrivilege
            FD_SeDebugPrivilege_Tmp4:
            push dword ptr [ebp+FD_SeDebugPrivilege_hProcessSnap]
            call dword ptr [ebx].xCloseHandle
            jmp NotFound_FD_SeDebugPrivilege
            Exit_FD_SeDebugPrivilege:
            pop edi
            pop ecx
            pop ebx
            assume ebx : nothing
            assume edi : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_FD_SeDebugPrivilege:
            xor eax, eax
            jmp Exit_FD_SeDebugPrivilege
            Found_FD_SeDebugPrivilege:
            mov eax, 1
            jmp Exit_FD_SeDebugPrivilege
            End_FD_SeDebugPrivilege:
            通過邏輯的判斷也可以找到調試器所在,一般來講程序都是有explorer.exe進程啟動的(通過雙擊)
            如果我們的進程的父進程不是explorer.exe則發現調試器。如果有調試的名稱冒名是explorer.exe
            那么我們判斷父進程ID后進一步判斷explorer.exe進程的路徑是否存在于Windows目錄下。如果不是
            則發現調試器。此類方法也可以也被病毒用作穿透仿真機。

            FD_Parent_Process:
            FD_Parent_Process_Arg_Win32Api equ 08h
            FD_Parent_Process_StackSize equ MAX_PATH + sizeof PROCESSENTRY32 + sizeof MODULEENTRY32 + 20h
            FD_Parent_Process_hParnet equ -04h
            FD_Parent_Process_PIDExplorer equ -08h
            FD_Parent_Process_PIDParent equ -0ch
            FD_Parent_Process_PIDChild equ -10h
            FD_Parent_Process_hSnapshot equ -14h
            FD_Parent_Process_pe32 equ -(20h + PROCESSENTRY32)
            FD_Parent_Process_me32 equ -(20h + PROCESSENTRY32 + MODULEENTRY32)
            FD_Parent_Process_lpszSystemInfo equ -(20h + PROCESSENTRY32 + MODULEENTRY32 + MAX_PATH)
            push ebp
            mov ebp, esp
            sub esp, FD_Parent_Process_StackSize

            push ebx
            push ecx
            push edi
            push esi

            ;; clear the stack
            lea edi, [ebp-FD_Parent_Process_StackSize]
            xor eax, eax
            mov ecx, FD_Parent_Process_StackSize
            cld
            rep stosb

            mov ebx, dword ptr [ebp+FD_Parent_Process_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            lea eax, [ebp+FD_Parent_Process_pe32]
            assume eax : ptr PROCESSENTRY32
            push sizeof PROCESSENTRY32
            pop dword ptr [eax].dwSize

            call dword ptr [ebx].xGetCurrentProcessId
            mov dword ptr [ebp+FD_Parent_Process_PIDChild], eax

            push 0
            push TH32CS_SNAPPROCESS
            call dword ptr [ebx].xCreateToolhelp32Snapshot
            mov dword ptr [ebp+FD_Parent_Process_hSnapshot], eax

            lea eax, [ebp+FD_Parent_Process_pe32]
            push eax
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xProcess32First
            test eax, eax
            jz FD_Parent_Process_Tmp1
            FD_Parent_Process_Loop1:
            lea eax, [ebp+FD_Parent_Process_pe32]
            push eax
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xProcess32Next
            test eax, eax
            jz FD_Parent_Process_Tmp2
            call FD_Parent_Process_Str1
            db "EXPLORER.EXE",0
            FD_Parent_Process_Str1:
            lea eax, [ebp+FD_Parent_Process_pe32]
            lea eax, [eax].szExeFile
            push eax
            call dword ptr [ebx].xlstrcmpiA
            jnz FD_Parent_Process_Tmp3
            mov eax, dword ptr [ebp+FD_Parent_Process_PIDExplorer]
            test eax, eax
            jnz FD_Parent_Process_Tmp3
            lea eax, [ebp+FD_Parent_Process_pe32]
            assume eax : ptr PROCESSENTRY32
            push dword ptr [eax].th32ProcessID
            pop dword ptr [ebp+FD_Parent_Process_PIDExplorer]
            FD_Parent_Process_Tmp3:
            lea eax, [ebp+FD_Parent_Process_pe32]
            mov eax, dword ptr [eax].th32ProcessID
            sub eax, dword ptr [ebp+FD_Parent_Process_PIDChild]
            jnz FD_Parent_Process_Tmp4
            lea eax, [ebp+FD_Parent_Process_pe32]
            push dword ptr [eax].th32ParentProcessID
            pop dword ptr [ebp+FD_Parent_Process_PIDParent]
            FD_Parent_Process_Tmp4:
            jmp FD_Parent_Process_Loop1
            FD_Parent_Process_Tmp1:
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xCloseHandle
            jmp NotFound_FD_Parent_Process
            FD_Parent_Process_Tmp2:
            mov eax, dword ptr [ebp+FD_Parent_Process_PIDExplorer]
            sub eax, dword ptr [ebp+FD_Parent_Process_PIDParent]
            jz FD_Parent_Process_Tmp5
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xCloseHandle
            jmp Found_FD_Parent_Process
            FD_Parent_Process_Tmp5:
            lea eax, [ebp+FD_Parent_Process_me32]
            assume eax : ptr MODULEENTRY32
            push sizeof MODULEENTRY32
            pop dword ptr [eax].dwSize
            push dword ptr [ebp+FD_Parent_Process_PIDExplorer]
            push TH32CS_SNAPMODULE
            call dword ptr [ebx].xCreateToolhelp32Snapshot
            mov dword ptr [ebp+FD_Parent_Process_hSnapshot], eax
            lea eax, [ebp+FD_Parent_Process_me32]
            push eax
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xModule32First
            test eax, eax
            jz FD_Parent_Process_Tmp6
            FD_Parent_Process_Loop2:
            lea eax, [ebp+FD_Parent_Process_me32]
            mov eax, dword ptr [eax].th32ProcessID
            sub eax, dword ptr [ebp+FD_Parent_Process_PIDExplorer]
            jnz FD_Parent_Process_Tmp7
            push MAX_PATH
            lea eax, [ebp+FD_Parent_Process_lpszSystemInfo]
            push eax
            call dword ptr [ebx].xGetWindowsDirectoryA
            call FD_Parent_Process_Str2
            db '\',0
            FD_Parent_Process_Str2:
            lea eax, [ebp+FD_Parent_Process_lpszSystemInfo]
            push eax
            call dword ptr [ebx].xlstrcatA
            call FD_Parent_Process_Str3
            db "EXPLORER.EXE",0
            FD_Parent_Process_Str3:
            lea eax, [ebp+FD_Parent_Process_lpszSystemInfo]
            push eax
            call dword ptr [ebx].xlstrcatA
            lea eax, [ebp+FD_Parent_Process_lpszSystemInfo]
            push eax
            lea eax, [ebp+FD_Parent_Process_me32]
            lea eax, [eax].szExePath
            push eax
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz FD_Parent_Process_Tmp6
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xCloseHandle
            jmp Found_FD_Parent_Process
            FD_Parent_Process_Tmp7:
            lea eax, [ebp+FD_Parent_Process_me32]
            push eax
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xModule32Next
            test eax, eax
            jnz FD_Parent_Process_Loop2
            FD_Parent_Process_Tmp6:
            push dword ptr [ebp+FD_Parent_Process_hSnapshot]
            call dword ptr [ebx].xCloseHandle
            jmp NotFound_FD_Parent_Process
            Exit_FD_Parent_Process:
            pop esi
            pop edi
            pop ecx
            pop ebx
            assume eax : nothing
            assume ebx : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_FD_Parent_Process:
            xor eax, eax
            jmp Exit_FD_Parent_Process
            Found_FD_Parent_Process:
            mov eax, 1
            jmp Exit_FD_Parent_Process
            End_FD_Parent_Process:
            當調試會話創建,將產生一個調試對象,我們通過ntdll中的
            NtQueryObject函數參看調試對象的個數是否不為零,來確定調試器的存在
            以ObjectAllTypeInformation使用NtQueryObject查詢后會返回一個
            OBJECT_ALL_INFORMATION的結構,其中NumberOfObjectsTypes成員為所有的
            對象類型在ObjectTypeInformation數組中的計數
            此對象如下
            typedef struct _OBJECT_ALL_INFORMATION
            ULONG NumberOfObjectsTypes;
            OBJECT_TYPE_INFORMATION ObjectTypeInformation[1];
            }
            typedef strcut _OBJECT_TYPE_INFORMATION {
            [00]UNICODE_STRING TypeName;
            [08]ULONG TotalNumberofHandles;
            [0c]ULONG TotalNumberofObjects;
            ...
            }
            循環遍歷ObjectTypeInformation對比類型的名字,如有類型名為DebugObject則
            檢測TotalNumberofHandles與TotalNumberofObjects如果不為0則存在調試器。

            FD_DebugObject_NtQueryObject:
            FD_DebugObject_NtQueryObject_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FD_DebugObject_NtQueryObject_Arg_Win32Api]

            push ebx
            push ecx
            push edx
            push edi
            push esi

            mov ebx, eax
            assume ebx : ptr WIN32APIBASE
            push edx ; alloc the stack

            push esp ; ReturnLength
            push 0
            push 0
            push ObjectAllTypeInformation
            push 0
            call dword ptr [ebx].xNtQueryObject
            pop ecx
            ;; make a tmp stack
            push ebp
            mov ebp, esp
            sub esp, ecx
            mov esi, esp
            ;; ObjectInformationLength
            push 0
            push ecx
            push esi
            push ObjectAllTypeInformation
            push 0
            call dword ptr [ebx].xNtQueryObject
            cld
            ;; NumberOfObjectsTypes
            lodsd
            xchg ecx, eax ; ecx = NumberOfObjectsTypes
            FD_DebugObject_NtQueryObject_Loop:
            ;; load string lengths
            lodsd
            movzx edx, ax
            ;; pointer to TypeName
            lodsd
            xchg esi, eax
            ;; sizeof(L"DebugObject")
            ;; avoids superstrings
            ;; like "DebugObjective"
            cmp edx, 16h
            jnz FD_DebugObject_NtQueryObject_Tmp2
            xchg ecx, edx
            FD_DebugObject_NtQueryObject_Tmp1:
            call FD_DebugObject_NtQueryObject_UnicodeStr1
            dw 'D','e','b','u','g'
            dw 'O','b','j','e','c','t'
            FD_DebugObject_NtQueryObject_UnicodeStr1:
            pop edi
            repe cmpsb
            xchg ecx, edx
            jnz FD_DebugObject_NtQueryObject_Tmp2
            ;; TotalNumberOfObjects
            cmp dword ptr [eax], edx
            jnz Found_FD_DebugObject_NtQueryObject
            ;; point to trailing null
            FD_DebugObject_NtQueryObject_Tmp2:
            add esi, edx
            ;; round down to dword
            and esi, -4
            ;; skip trailing null
            ;; and any alignment bytes
            lodsd
            loop FD_DebugObject_NtQueryObject_Loop
            xor eax, eax
            Exit_FD_DebugObject_NtQueryObject:
            ;; clear the tmp stack
            mov esp, ebp
            pop ebp

            pop esi
            pop edi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            retn 04h
            Found_FD_DebugObject_NtQueryObject:
            mov eax, 1
            jmp Exit_FD_DebugObject_NtQueryObject
            End_FD_DebugObject_NtQueryObject:
            此類方法,利用FindWindow函數通過尋找是否存在一些常見調試軟件的Title。這里收集了一些
            如果有其他的Title,請朋友們告知。。。

            FD_Find_Debugger_Window:
            FD_Find_Debugger_Window_Arg_WinApi32 equ 08h
            push ebp
            mov ebp, esp

            push ebx

            mov ebx, dword ptr [ebp+FD_Find_Debugger_Window_Arg_WinApi32]
            assume ebx : ptr WIN32APIBASE

            push NULL
            call FD_Find_Debugger_Window_Str1
            db "1212121",0
            FD_Find_Debugger_Window_Str1:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str2
            db "icu_dbg",0
            FD_Find_Debugger_Window_Str2:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str3
            db "pe--diy",0
            FD_Find_Debugger_Window_Str3:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str5
            db "ollydbg",0
            FD_Find_Debugger_Window_Str5:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str6
            db "odbydyk",0
            FD_Find_Debugger_Window_Str6:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str7
            db "WinDbgFrameClass",0
            FD_Find_Debugger_Window_Str7:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str8
            db "TDeDeMainForm",0
            FD_Find_Debugger_Window_Str8:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str9
            db "TIdaWindow",0
            FD_Find_Debugger_Window_Str9:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrA
            db "TESTDBG",0
            FD_Find_Debugger_Window_StrA:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrB
            db "kk1",0
            FD_Find_Debugger_Window_StrB:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrC
            db "Eew75",0
            FD_Find_Debugger_Window_StrC:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrD
            db "Shadow",0
            FD_Find_Debugger_Window_StrD:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrE
            db "PEiD v0.94",0
            FD_Find_Debugger_Window_StrE:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_StrF
            db "Registry Monitor - Sysinternals: www.sysinternals.com",0
            FD_Find_Debugger_Window_StrF:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str10
            db "File Monitor - Sysinternals: www.sysinternals.com",0
            FD_Find_Debugger_Window_Str10:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window

            push NULL
            call FD_Find_Debugger_Window_Str11
            db "Import REConstructor v1.6 FINAL (C) 2001-2003 MackT/uCF",0
            FD_Find_Debugger_Window_Str11:
            call dword ptr [ebx].xFindWindowA
            test eax, eax
            jnz Found_FD_Find_Debugger_Window
            jmp NotFound_Found_FD_Find_Debugger_Window
            Exit_FD_Find_Debugger_Window:
            pop ebx
            assume ebx : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_Found_FD_Find_Debugger_Window:
            xor eax, eax
            jmp Exit_FD_Find_Debugger_Window
            Found_FD_Find_Debugger_Window:
            mov eax, 1
            jmp Exit_FD_Find_Debugger_Window
            End_FD_Find_Debugger_Window:
            這種方面的核心思想是比對在進程表中是否是出現了調試器進程名,如果出現則退出。
            不過這種方法很容易躲過,而且也可能造成誤判。

            FD_Find_Debugger_Process:
            FD_Find_Debugger_Process_Arg_Win32Api equ 08h
            FD_Find_Debugger_Process_StackSize equ 10h + sizeof PROCESSENTRY32
            FD_Find_Debugger_Process_hSnapshot equ -04h
            FD_Find_Debugger_Process_hParnet equ -08h
            FD_Find_Debugger_Process_pe32 equ -(10+sizeof PROCESSENTRY32)

            push ebp
            mov ebp, esp
            sub esp, FD_Find_Debugger_Process_StackSize

            push edi
            push esi
            push edx
            push ecx
            push ebx

            ;; clear the stack
            lea edi, [ebp-FD_Find_Debugger_Process_StackSize]
            mov ecx, FD_Find_Debugger_Process_StackSize
            xor eax, eax
            cld
            rep stosb

            mov ebx, dword ptr [ebp+FD_Find_Debugger_Process_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            lea esi, [ebp+FD_Find_Debugger_Process_pe32]
            assume esi : ptr PROCESSENTRY32
            push sizeof PROCESSENTRY32
            pop dword ptr [esi].dwSize

            push 0
            push TH32CS_SNAPPROCESS
            call dword ptr [ebx].xCreateToolhelp32Snapshot
            mov dword ptr [ebp+FD_Find_Debugger_Process_hSnapshot], eax
            lea eax, [ebp+FD_Find_Debugger_Process_pe32]
            push eax
            push dword ptr [ebp+FD_Find_Debugger_Process_hSnapshot]
            call dword ptr [ebx].xProcess32First
            test eax, eax
            jz NotFound_FD_Find_Debugger_Process
            FD_Find_Debugger_Process_Loop:
            lea eax, [esi].szExeFile
            mov edi, eax
            call FD_Find_Debugger_Process_Str1
            db "OLLYICE.EXE",0
            FD_Find_Debugger_Process_Str1:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str2
            db "IDAG.EXE",0
            FD_Find_Debugger_Process_Str2:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str3
            db "OLLYDBG.EXE",0
            FD_Find_Debugger_Process_Str3:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str4
            db "PEID.EXE",0
            FD_Find_Debugger_Process_Str4:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str5
            db "SOFTICE.EXE",0
            FD_Find_Debugger_Process_Str5:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str6
            db "LORDPE.EXE",0
            FD_Find_Debugger_Process_Str6:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str7
            db "IMPORTREC.EXE",0
            FD_Find_Debugger_Process_Str7:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str8
            db "W32DSM89.EXE",0
            FD_Find_Debugger_Process_Str8:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process

            call FD_Find_Debugger_Process_Str9
            db "WINDBG.EXE",0
            FD_Find_Debugger_Process_Str9:
            push edi
            call dword ptr [ebx].xlstrcmpiA
            test eax, eax
            jz Found_FD_Find_Debugger_Process
            lea eax, [ebp+FD_Find_Debugger_Process_pe32]
            push eax
            push dword ptr [ebp+FD_Find_Debugger_Process_hSnapshot]
            call dword ptr [ebx].xProcess32Next
            test eax, eax
            jnz FD_Find_Debugger_Process_Loop
            jmp NotFound_FD_Find_Debugger_Process
            Exit_FD_Find_Debugger_Process:
            ;; close the Shotsnap handle
            push dword ptr [ebp+FD_Find_Debugger_Process_hSnapshot]
            call dword ptr [ebx].xCloseHandle

            pop edi
            pop esi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            assume esi : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_FD_Find_Debugger_Process:
            xor eax, eax
            jmp Exit_FD_Find_Debugger_Process
            Found_FD_Find_Debugger_Process:
            mov eax, 1
            jmp Exit_FD_Find_Debugger_Process
            End_FD_Find_Debugger_Process:
            這種方法通過打開一些調試軟件加載到系統中驅動的句柄,從而判斷是否有
            調試軟件的存在。

            FD_Find_Device_Driver:
            FD_Find_Device_Driver_Arg_Win32Api equ 08h

            push ebp
            mov ebp, esp

            push ebx
            push ecx
            push edx
            push esi
            push edi

            mov ebx, dword ptr [ebp+FD_Find_Device_Driver_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            ;; check softice on unknow system
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str1
            db "\\.\SIWVID",0
            FD_Find_Device_Driver_Str1:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check softice 4.05 on win2k
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str2
            db "\\.\NTICE",0
            FD_Find_Device_Driver_Str2:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check softice on win9x
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str3
            db "\\.\SICE",0
            FD_Find_Device_Driver_Str3:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check softice on win9x
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str4
            db "\\.\SIWDEBUG",0
            FD_Find_Device_Driver_Str4:
            call dword ptr [ebx].xCreateFileA
            push eax
            call dword ptr [ebx].xGetLastError
            test al, 032h
            pop eax
            jz Found_FD_Find_Device_Driver

            ;; check regmon on win9x
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str5
            db "\\.\REGVXD",0
            FD_Find_Device_Driver_Str5:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check RegMON
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str6
            db "\\.\FILEM",0
            FD_Find_Device_Driver_Str6:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check TRW
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str7
            db "\\.\TRW",0
            FD_Find_Device_Driver_Str7:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver

            ;; check softice extender
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ + FILE_SHARE_WRITE
            push GENERIC_READ + GENERIC_WRITE
            call FD_Find_Device_Driver_Str8
            db "\\.\ICEEXT",0
            FD_Find_Device_Driver_Str8:
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jnz Found_FD_Find_Device_Driver
            jmp NotFound_FD_Find_Device_Driver

            Exit_FD_Find_Device_Driver:
            pop edi
            pop esi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_FD_Find_Device_Driver:
            xor eax, eax
            jmp Exit_FD_Find_Device_Driver
            Found_FD_Find_Device_Driver:
            push eax
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xCloseHandle
            assume ebx : nothing
            mov eax, 1
            jmp Exit_FD_Find_Device_Driver
            End_FD_Find_Device_Driver:
            利用int3中斷引起異常。如果,正常運行則觸發異常。

            FD_Exception_Int3:
            call Get_FD_Exception_Int3_Eip
            Get_FD_Exception_Int3_Eip:
            pop eax
            add eax, offset FD_Exception_Int3_Exception - offset Get_FD_Exception_Int3_Eip
            ;; setup exception
            assume fs : nothing
            push eax
            push dword ptr fs : [0]
            mov dword ptr fs : [0], esp
            ;; reset eax
            xor eax, eax
            int 03h
            ;; unsetup exception
            pop dword ptr fs : [0]
            add esp, 04h

            ;; check the flag
            test eax, eax
            jz Found_FD_Exception_Int3
            jmp NotFound_FD_Exception_Int3
            FD_Exception_Int3_Exception:
            mov eax, dword ptr [esp+0ch]
            ;; eax = ContextRecord
            assume eax : ptr CONTEXT
            mov dword ptr [eax].regEax, 0FFFFFFFFh
            inc dword ptr [eax].regEip
            xor eax, eax
            assume eax : nothing
            retn
            Exit_FD_Exception_Int3:
            retn 0h
            NotFound_FD_Exception_Int3:
            xor eax, eax
            jmp Exit_FD_Exception_Int3
            Found_FD_Exception_Int3:
            mov eax, 1
            jmp Exit_FD_Exception_Int3
            End_FD_Exception_Int3:
            通過對EFLAGS中的TF的檢測來確定是否存在調試器。當TF=1的時會觸發一個
            單步執行異常,可以通過安裝異常處理針來捕獲。

            FD_Exception_Popf:
            push ebx

            call Get_FD_Exception_Popf_Eip
            Get_FD_Exception_Popf_Eip:
            pop eax
            add eax, offset FD_Exception_Popf_Exception - offset Get_FD_Exception_Popf_Eip
            assume fs : nothing
            push eax
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp
            ;; reset eax
            xor eax, eax
            pushf
            mov dword ptr [esp], 0100h
            popf
            nop
            FD_Exception_Popf_NextEip:
            pop dword ptr fs:[0]
            add esp, 04h

            ;; check the flag
            test eax, eax
            jz Found_FD_Exception_Popf
            jmp NotFound_FD_Exception_Popf

            FD_Exception_Popf_Exception:
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            mov dword ptr [eax].regEax, 0FFFFFFFFh
            call Get_FD_Exception_Popf_Exception_Eip2
            Get_FD_Exception_Popf_Exception_Eip2:
            pop ebx
            sub ebx, offset Get_FD_Exception_Popf_Exception_Eip2 - offset FD_Exception_Popf_NextEip
            mov dword ptr [eax].regEip, ebx
            xor eax, eax
            retn
            assume eax : nothing
            Exit_FD_Exception_Popf:
            pop ebx
            retn 0h
            NotFound_FD_Exception_Popf:
            xor eax, eax
            jmp Exit_FD_Exception_Popf
            Found_FD_Exception_Popf:
            mov eax, 1
            jmp Exit_FD_Exception_Popf
            End_FD_Exception_Popf:
            觸發OutputDebugString的錯誤。如果調試器存在則GetLastError為0。

            FD_OutputDebugString:
            FD_OutputDebugString_Arg_Win32Api equ 04h

            mov eax, dword ptr [esp+FD_OutputDebugString_Arg_Win32Api]
            push ebx
            mov ebx, eax
            assume ebx : ptr WIN32APIBASE
            call FD_OutputDebugString_Str
            db 0
            FD_OutputDebugString_Str:
            call dword ptr [ebx].xOutputDebugStringA
            call dword ptr [ebx].xGetLastError
            test eax, eax
            jnz NotFound_FD_OutputDebugString
            inc eax
            pop ebx
            assume ebx : nothing
            retn 04h
            NotFound_FD_OutputDebugString:
            pop ebx
            xor eax, eax
            retn 04h

            End_FD_OutputDebugString:
            Ollydbg允許設置一個內存訪問/寫入斷點。它通過頁面保護來實現。
            頁面保護提供了當應用程序的某塊內存被訪問時獲得通知。
            頁面保護通過PAGE_GUARD頁面保護修改符來設置。如果訪問的內存
            是受保護的將會產生一個STATUS_GUARD_PAGE_VIOLATION(0x80000001)異常
            如果進程被Ollydbg調試并且受保護的頁面被訪問,將不會拋出異常。訪問
            將會被當作內存斷點來處理。

            FS_OD_Exception_GuardPages:
            FS_OD_Exception_GuardPages_Arg_Win32Api equ 04h

            mov eax, dword ptr [esp+FS_OD_Exception_GuardPages_Arg_Win32Api]

            push edi ; pAllocatedMem
            push ebx

            mov ebx, eax
            assume ebx : ptr WIN32APIBASE

            push PAGE_READWRITE
            push MEM_COMMIT
            push 01000h
            push NULL
            call dword ptr [ebx].xVirtualAlloc
            test eax, eax
            jz NotFound_FS_OD_Exception_GuardPages
            mov edi, eax
            ;; store a RENT on the allocated memory
            mov byte ptr [edi], 0c3h
            push edi ; alloc stack

            push esp
            push PAGE_EXECUTE_READ + PAGE_GUARD
            push 01000h
            push edi
            call dword ptr [ebx].xVirtualProtect
            ;; set eax to 0
            xor eax, eax
            ;; trigger a STATUS_GUARD_PAGE_VIOLATION exception
            ;; setup expcetion
            call Get_FS_OD_Exception_GuardPages_Eip
            Get_FS_OD_Exception_GuardPages_Eip:
            pop eax
            add eax, offset FS_OD_Exception_GuardPages_Exception - offset Get_FS_OD_Exception_GuardPages_Eip
            assume fs : nothing
            push eax
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp
            call edi
            FS_OD_Exception_GuardPages_Continue:
            pop edi
            ;; unsetup exception
            pop dword ptr fs:[0]
            add esp, 04h
            test eax, eax
            jz Found_FS_OD_Exception_GuardPages
            jmp NotFound_FS_OD_Exception_GuardPages
            FS_OD_Exception_GuardPages_Exception:
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            mov dword ptr [eax].regEax, 0FFFFFFFFh
            call Get_FS_OD_Exception_GuardPages_Exception_Eip
            Get_FS_OD_Exception_GuardPages_Exception_Eip:
            pop ebx
            sub ebx, offset Get_FS_OD_Exception_GuardPages_Exception_Eip - offset FS_OD_Exception_GuardPages_Continue
            mov dword ptr [eax].regEip, ebx
            assume eax : nothing
            xor eax, eax
            retn

            Exit_FS_OD_Exception_GuardPages:
            pop ebx
            pop edi
            assume ebx : nothing
            retn 04h

            NotFound_FS_OD_Exception_GuardPages:
            assume ebx : ptr WIN32APIBASE
            push MEM_DECOMMIT
            push 01000h
            push edi
            call dword ptr [ebx].xVirtualFree
            assume ebx : nothing
            xor eax, eax
            jmp Exit_FS_OD_Exception_GuardPages
            Found_FS_OD_Exception_GuardPages:
            assume ebx : ptr WIN32APIBASE
            push MEM_DECOMMIT
            push 01000h
            push edi
            call dword ptr [ebx].xVirtualFree
            assume ebx : nothing
            mov eax, 1
            jmp Exit_FS_OD_Exception_GuardPages
            End_FS_OD_Exception_GuardPages:
            Softice調試器會對UnhandleExceptionFilter進行修改,將第一個字節修改為CCh(int 3)

            FS_SI_UnhandledExceptionFilter:
            FS_SI_UnhandledExceptionFilter_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FS_SI_UnhandledExceptionFilter_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            mov eax, dword ptr [eax].xUnhandledExceptionFilter
            mov al, byte ptr [eax]
            sub al, 0cch
            jz Found_FS_SI_UnhandledExceptionFilter
            xor eax, eax
            Exit_FS_SI_UnhandledExceptionFilter:
            assume eax : nothing
            retn 04h
            Found_FS_SI_UnhandledExceptionFilter:
            mov eax, 1
            jmp Exit_FS_SI_UnhandledExceptionFilter
            End_FS_SI_UnhandledExceptionFilter:
            Ollydbg的插件對幾個函數的首部進行修改。通過對齊的檢測來判斷系統中是否存在調試器

            FS_ODP_Process32NextW:
            FS_ODP_Process32NextW_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FS_ODP_Process32NextW_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            mov eax, dword ptr [eax].xProcess32NextW
            mov ax, word ptr [eax]
            sub ax, 0FF88h
            jnz Found_FS_ODP_Process32NextW
            xor eax, eax
            Exit_FS_ODP_Process32NextW:
            assume eax : nothing
            retn 04h
            Found_FS_ODP_Process32NextW:
            mov eax, 1
            jmp Exit_FS_ODP_Process32NextW
            End_FS_ODP_Process32NextW:


            FS_ODP_OutputDebugStringA:
            FS_ODP_OutputDebugStringA_Arg_Win32Api equ 04h
            mov eax, dword ptr [ebp+FS_ODP_OutputDebugStringA_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            mov eax, dword ptr [eax].xOutputDebugStringA
            mov ax, word ptr [eax]
            sub ax, 03468h
            jnz Found_FS_ODP_OutputDebugStringA
            xor eax, eax
            Exit_FS_ODP_OutputDebugStringA:
            assume eax : nothing
            retn 04h
            Found_FS_ODP_OutputDebugStringA:
            mov eax, 1
            jmp Exit_FS_ODP_OutputDebugStringA
            End_FS_ODP_OutputDebugStringA:


            FS_ODP_OpenProcess:
            FS_ODP_OpenProcess_Arg_Win32Api equ 04h
            mov eax, dword ptr [ebp+FS_ODP_OpenProcess_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            mov eax, dword ptr [eax].xOpenProcess
            mov al, byte ptr [eax+06h]
            ;; Hide Debugger Plugin of OD is present
            sub al, 0eah
            jnz Found_FS_ODP_OpenProcess
            xor eax, eax
            Exit_FS_ODP_OpenProcess:
            assume eax : nothing
            retn 04h
            Found_FS_ODP_OpenProcess:
            mov eax, 1
            jmp Exit_FS_ODP_OpenProcess
            End_FS_ODP_OpenProcess:

            FB_HWBP_Exception:
            call Get_FB_HWBP_Exception_Eip
            Get_FB_HWBP_Exception_Eip:
            pop eax
            add eax, offset FB_HWBP_Exception_Exception - offset FB_HWBP_Exception
            assume fs : nothing
            push eax
            push fs:[0]
            mov dword ptr fs:[0], esp
            ;; reset eax
            xor eax, eax
            int 01h
            pop dword ptr fs:[0]
            add esp, 04h
            test eax, eax
            jnz Found_FB_HWBP_Exception
            jmp NotFound_FB_HWBP_Exception
            FB_HWBP_Exception_Exception:
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            ;; check if debug Registers Context.Dr0-Dr3 is not zero
            cmp dword ptr [eax].iDr0, 0
            jnz FB_HWBP_Exception_HardwareBp_Found
            cmp dword ptr [eax].iDr1, 0
            jnz FB_HWBP_Exception_HardwareBp_Found
            cmp dword ptr [eax].iDr2, 0
            jnz FB_HWBP_Exception_HardwareBp_Found
            cmp dword ptr [eax].iDr3, 0
            jnz FB_HWBP_Exception_HardwareBp_Found
            jmp FB_HWBP_Exception_Exception_Ret
            FB_HWBP_Exception_HardwareBp_Found:
            ;; set Context.Eax to signal breakpoint found
            mov dword ptr [eax].regEax, 0FFFFFFFFh
            FB_HWBP_Exception_Exception_Ret:
            ;; set Context.Eip upon return
            add dword ptr [eax].regEip, 02h
            xor eax, eax
            retn
            Exit_FB_HWBP_Exception:
            retn 0h
            NotFound_FB_HWBP_Exception:
            xor eax, eax
            jmp Exit_FB_HWBP_Exception
            Found_FB_HWBP_Exception:
            mov eax, 1
            jmp Exit_FB_HWBP_Exception
            End_FB_HWBP_Exception:
            通過對代碼節做CRC值的驗證來判斷是否存在內存補丁

            FB_SWBP_Memory_CRC:
            FB_SWBP_Memory_CRC_Arg_Win32Api equ 08h
            FB_SWBP_Memory_CRC_Arg_FuncAddr equ 0ch
            FB_SWBP_Memory_CRC_StackSize equ 10h+MAX_PATH
            FB_SWBP_Memory_CRC_fileSize equ -04h
            FB_SWBP_Memory_CRC_NumberOfBytesRW equ -08h
            FB_SWBP_Memory_CRC_pBuffer equ -0ch
            FB_SWBP_Memory_CRC_szFileName equ -(10h+MAX_PATH)
            push ebp
            mov ebp, esp
            sub esp, FB_SWBP_Memory_CRC_StackSize

            push esi
            push edi
            push ecx
            push edx
            push ebx


            ;; clear the stack
            lea edi, [ebp+FB_SWBP_Memory_CRC_szFileName]
            mov ecx, FB_SWBP_Memory_CRC_StackSize
            xor eax, eax
            cld
            rep stosb


            mov ebx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            push MAX_PATH
            lea eax, [ebp+FB_SWBP_Memory_CRC_szFileName]
            push eax
            push NULL
            call dword ptr [ebx].xGetModuleFileNameA
            ;; open file
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ
            push GENERIC_READ
            lea eax, [ebp+FB_SWBP_Memory_CRC_szFileName]
            push eax
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jz Error_FB_SWBP_Memory_CRC
            mov edi, eax
            push NULL
            push eax
            call dword ptr [ebx].xGetFileSize
            ; cmp eax, INVALID_FILE_SIZE
            ; jz Error_FB_SWBP_Memory_CRC
            mov dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize], eax
            push PAGE_READWRITE
            push MEM_COMMIT
            push eax
            push NULL
            call dword ptr [ebx].xVirtualAlloc
            mov dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer], eax
            push NULL
            lea eax, [ebp+FB_SWBP_Memory_CRC_NumberOfBytesRW]
            push eax
            push dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize]
            push dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            push edi
            call dword ptr [ebx].xReadFile
            push edi
            call dword ptr [ebx].xCloseHandle

            mov esi, dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            add esi, dword ptr [esi+3ch]
            assume esi : ptr IMAGE_NT_HEADERS
            mov edx, dword ptr [esi].OptionalHeader.ImageBase
            mov eax, dword ptr [esi].OptionalHeader.AddressOfEntryPoint
            add eax, edx
            mov cx, word ptr [esi].FileHeader.NumberOfSections
            movzx ecx, cx
            mov edi, esi
            add edi, sizeof IMAGE_NT_HEADERS
            assume edi : ptr IMAGE_SECTION_HEADER
            ;; find the entry section
            ;; eax = AddressOfEntryPoint
            ;; ebx = Each Section Virtual Address
            ;; ecx = NumberOfSections
            ;; edx = ImageBase
            ;; edi = Section Table Point
            FB_SWBP_Memory_CRC_Loop:
            mov ebx, dword ptr [edi].VirtualAddress
            add ebx, edx
            cmp ebx, eax
            jz FB_SWBP_Memory_CRC_Loop_End
            add edi, sizeof IMAGE_SECTION_HEADER
            dec ecx
            jnz FB_SWBP_Memory_CRC_Loop
            jmp Error_FB_SWBP_Memory_CRC
            FB_SWBP_Memory_CRC_Loop_End:
            mov edi, dword ptr [edi].Misc.VirtualSize
            mov esi, eax
            ;; alloc the memory
            push MEM_DECOMMIT
            push dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize]
            push dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            mov ebx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xVirtualFree
            mov edx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_FuncAddr]
            assume edx : ptr FUNCADDRTBL
            push edi
            push esi
            call dword ptr [edx].xCRC32
            call Get_FB_SWBP_Memory_CRC_Eip
            Get_FB_SWBP_Memory_CRC_Eip:
            pop ecx
            add ecx, offset FB_SWBP_Memory_CRC_Orig_CRC - offset Get_FB_SWBP_Memory_CRC_Eip
            cmp eax, ecx
            jz NotFound_FB_SWBP_Memory_CRC
            jmp Found_FB_SWBP_Memory_CRC
            Exit_FB_SWBP_Memory_CRC:
            pop ebx
            pop edx
            pop ecx
            pop edi
            pop esi
            assume ebx : nothing
            assume edx : nothing
            assume edi : nothing
            assume esi : nothing
            mov esp, ebp
            pop ebp
            retn 08h
            Error_FB_SWBP_Memory_CRC:
            mov eax, dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            test eax, eax
            jz Error_FB_SWBP_Memory_CRC_Continue
            push MEM_DECOMMIT
            push dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize]
            push dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            mov ebx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xVirtualFree
            assume ebx : nothing
            Error_FB_SWBP_Memory_CRC_Continue:
            xor eax, eax
            jmp Exit_FB_SWBP_Memory_CRC
            Found_FB_SWBP_Memory_CRC:
            push MEM_DECOMMIT
            push dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize]
            push dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            mov ebx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xVirtualFree
            assume ebx : nothing
            mov eax, 1
            jmp Exit_FB_SWBP_Memory_CRC
            NotFound_FB_SWBP_Memory_CRC:
            push MEM_DECOMMIT
            push dword ptr [ebp+FB_SWBP_Memory_CRC_fileSize]
            push dword ptr [ebp+FB_SWBP_Memory_CRC_pBuffer]
            mov ebx, dword ptr [ebp+FB_SWBP_Memory_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xVirtualFree
            assume ebx : nothing
            xor eax, eax
            jmp Exit_FB_SWBP_Memory_CRC
            FB_SWBP_Memory_CRC_Orig_CRC:
            dd 0
            End_FB_SWBP_Memory_CRC:
            通過檢測標志位來檢測是否存在單步運行標志

            FT_PushSS_PopSS:
            ;; release version
            push ebp
            mov ebp, esp
            push ss
            pop ss
            pushf
            pop eax
            and eax, 00000100h
            jnz Found_FT_PushSS_PopSS
            Exit_FT_PushSS_PopSS:
            xor eax, eax
            mov esp, ebp
            pop ebp
            retn 0h
            Found_FT_PushSS_PopSS:
            mov eax, 1
            jmp Exit_FT_PushSS_PopSS
            End_FT_PushSS_PopSS:
            以下三個函數都是通過調用取單步運行時間差的原理來檢測是否進行單步運行的
            分別使用了rdtsc,GetTickCount,timeGetTime三個函數來確定

            FT_RDTSC:
            push ecx
            rdtsc
            xchg ecx, eax
            rdtsc
            sub eax, ecx
            cmp eax, 500h
            jnbe Found_FT_RDTSC
            xor eax, eax
            Exit_FT_RDTSC:
            pop ecx
            retn 0h
            Found_FT_RDTSC:
            mov eax, 1
            jmp Exit_FT_RDTSC
            End_FT_RDTSC:

            FT_GetTickCount:
            FT_GetTickCount_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FT_GetTickCount_Arg_Win32Api]
            push ebx
            push ecx
            mov ebx, eax
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xGetTickCount
            xchg ecx, eax
            call dword ptr [ebx].xGetTickCount
            sub eax, ebx
            cmp eax, 1
            jnb Found_FT_GetTickCount
            xor eax, eax
            Exit_FT_GetTickCount:
            pop ecx
            pop ebx
            assume ebx : nothing
            retn 04h
            Found_FT_GetTickCount:
            mov eax, 1
            jmp Exit_FT_GetTickCount
            End_FT_GetTickCount:

            FT_timeGetTime:
            FT_timeGetTime_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+FT_timeGetTime_Arg_Win32Api]
            push ebx
            push ecx
            mov ebx, eax
            assume ebx : ptr WIN32APIBASE
            call dword ptr [ebx].xtimeGetTime
            xchg ecx, eax
            call dword ptr [ebx].xtimeGetTime
            sub eax, ebx
            cmp eax, 10h
            jnb Found_FT_timeGetTime
            xor eax, eax
            Exit_FT_timeGetTime:
            pop ecx
            pop ebx
            assume ebx : nothing
            retn 04h
            Found_FT_timeGetTime:
            mov eax, 1
            jmp Exit_FT_timeGetTime
            End_FT_timeGetTime:
            手動檢測位于7FFE0000h地址的SharedUserData數據結構的TickCoutLow與TickCountMultipiler字段
            來獲取單步運行時間差。

            FT_SharedUserData_TickCount:
            push ecx
            push edx
            mov edx, 07FFE0000h
            mov eax, dword ptr [edx]
            imul dword ptr [edx+04h]
            shrd eax, edx, 018h
            xchg eax, ecx
            mov edx, 07FFE0000h
            mov eax, dword ptr [edx]
            imul dword ptr [edx+04h]
            shrd eax, edx, 018h
            sub eax, ecx
            cmp eax, 500h
            jnbe Found_FT_SharedUserData_TickCount
            xor eax, eax
            Exit_FT_SharedUserData_TickCount:
            pop edx
            pop ecx
            retn 0h
            Found_FT_SharedUserData_TickCount:
            mov eax, 1
            jmp Exit_FT_SharedUserData_TickCount
            End_FT_SharedUserData_TickCount:
            中斷1不能從r3下調用。如果從r3下調用,將產生一個EXECEPTION_ACCESS_VIOLATION(0x0C0000005)的異常。
            如果softice存在,它HOOK了中斷1并且使它的DPL(descriptor privilege level)到環3下
            使得softice能單步處理用戶態的程序。如果程序使用中斷1,softice不檢查它是否在單步運行或者是一軟中斷。
            softice總是調用原始的中斷1處理函數。并且使用EXCEPTION_SINGLE_STEP(0x80000004)異常替換原本的EXECEPTION_ACCESS_VIOLATION
            (0xC0000005)異常。

            FT_INT1_IceBreakpoint:
            push ebp
            mov ebp, esp
            call Get_FT_INT1_IceBreakpoint_Eip
            Get_FT_INT1_IceBreakpoint_Eip:
            pop eax
            add eax, offset FT_INT1_IceBreakpoint_Exception - offset Get_FT_INT1_IceBreakpoint_Eip
            push eax
            assume fs : nothing
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp
            ;; reset eax
            xor eax, eax
            db 0CDh, 01h ; int 1
            pop dword ptr fs:[0]
            add esp, 04h
            test eax, eax
            jz Found_FT_INT1_IceBreakpoint
            jmp NotFound_FT_INT1_IceBreakpoint
            FT_INT1_IceBreakpoint_Exception:
            ;mov eax, dword ptr [esp+04h]
            ;cmp dword ptr [eax], 80000004h
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            mov dword ptr [eax].regEax, 1
            inc dword ptr [eax].regEip
            xor eax, eax
            retn
            Exit_FT_INT1_IceBreakpoint:
            mov esp, ebp
            pop ebp
            retn 0h
            NotFound_FT_INT1_IceBreakpoint:
            xor eax, eax
            jmp Exit_FT_INT1_IceBreakpoint
            Found_FT_INT1_IceBreakpoint:
            mov eax, 1
            jmp Exit_FT_INT1_IceBreakpoint
            End_FT_INT1_IceBreakpoint:
            以下為檢測Virtual PC 與 VMWARE的兩個例子,這類檢測技術大多都是通過與真實環境中不同的
            異常,指令實現的。嚴格的描述可以在其規定的文檔中找到。

            FV_VPC_Exception:

            push ebx
            push ecx

            call Get_FV_VPC_Exception_Eip
            Get_FV_VPC_Exception_Eip:
            pop ecx
            add ecx, offset FV_VPC_Exception_Exception - offset Get_FV_VPC_Exception_Eip
            assume fs : nothing
            push ecx
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp

            ;; Flag
            xor ebx, ebx
            ;; VPC function number
            mov eax, 1

            ;; call VPC
            db 0Fh,3Fh,07h,0Bh

            pop dword ptr fs:[0]
            add esp, 04h
            test ebx, ebx
            setz al

            pop ecx
            pop ebx
            retn 0h

            FV_VPC_Exception_Exception:
            mov ecx, dword ptr [esp+0ch]
            assume ecx : ptr CONTEXT
            ;; ebx = -1 : not running
            ;; ebx = 0 : running
            mov dword ptr [ecx].regEbx, -1
            ;; skip past the call to VPC
            add dword ptr [ecx].regEip, 04h
            xor eax, eax
            retn
            End_FV_VPC_Exception:

            FV_VMWare_VMX:

            call IsInsideVMWare
            retn 0h
            IsInsideVMWare:

            push ebx
            push ecx
            push edx

            assume fs : nothing
            call Get_IsInsideVMWare_Eip
            Get_IsInsideVMWare_Eip:
            pop eax
            add eax, offset IsInsideVMWare_Exception - offset Get_IsInsideVMWare_Eip
            push eax
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp

            mov eax, 'VMXh'
            mov ebx, 0 ; any value but MAGIC VALUE
            mov ecx, 10 ; get VMWare version
            mov edx, 'VX' ; port number
            in eax, dx ; read port
            ; on return EAX returns the VERSION
            cmp ebx, 'VMXh' ; is it a reply from VMWare?
            setz al ; set return value
            movzx eax, al

            pop dword ptr fs:[0]
            add esp, 04h

            pop edx
            pop ecx
            pop ebx

            retn 0h
            IsInsideVMWare_Exception:
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            inc dword ptr [eax].regEip
            retn
            End_IsInsideVMWare:

            End_FV_VMWare_VMX:
            通過計算文件的長度與原先的對比,來確定是否進行過修改。來發現補丁。

            FP_Check_FileSize:
            FP_Check_FileSize_Arg_Win32Api equ 08h
            FP_Check_FileSize_StackSize equ MAX_PATH
            FP_Check_FileSize_szPath equ -MAX_PATH
            push ebp
            mov ebp, esp
            sub esp, FP_Check_FileSize_StackSize

            push ebx
            push ecx
            push edx
            mov ebx, dword ptr [ebp+FP_Check_FileSize_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push MAX_PATH
            lea eax, [ebp+FP_Check_FileSize_szPath]
            push eax
            push NULL
            call dword ptr [ebx].xGetModuleFileNameA
            test eax, eax
            jz NotFound_FP_Check_FileSize

            ;; create file
            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_ALWAYS
            push NULL
            push FILE_SHARE_READ
            push GENERIC_READ
            lea eax, [ebp+FP_Check_FileSize_szPath]
            push eax
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jz NotFound_FP_Check_FileSize
            mov ecx, eax

            push NULL
            push eax
            call dword ptr [ebx].xGetFileSize
            mov edx, eax

            push ecx
            call dword ptr [ebx].xCloseHandle

            call Get_FP_Check_FileSize_Eip
            Get_FP_Check_FileSize_Eip:
            pop eax
            add eax, offset FP_Check_FileSize_Orig_Size - offset Get_FP_Check_FileSize_Eip
            cmp edx, eax
            jnz Found_FP_Check_FileSize
            jmp NotFound_FP_Check_FileSize

            Exit_FP_Check_FileSize:
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing

            mov esp, ebp
            pop ebp
            retn 04h
            NotFound_FP_Check_FileSize:
            xor eax, eax
            jmp Exit_FP_Check_FileSize
            Found_FP_Check_FileSize:
            mov eax, 1
            jmp Exit_FP_Check_FileSize
            FP_Check_FileSize_Orig_Size:
            dd 0
            End_FP_Check_FileSize:
            通過計算文件的CRC值來對比是否被Cracker進行過修改打過補丁。

            FP_Check_FileHashValue_CRC:
            FP_Check_FileHashValue_CRC_Arg_Win32Api equ 08h
            FP_Check_FileHashValue_CRC_Arg_FuncAddr equ 0ch
            FP_Check_FileHashValue_CRC_StackSize equ 20h+MAX_PATH
            FP_Check_FileHashValue_CRC_fileSize equ -04h
            FP_Check_FileHashValue_CRC_NumberOfBytesRW equ -08h
            FP_Check_FileHashValue_CRC_CRCVALUE_current equ -0ch
            FP_Check_FileHashValue_CRC_pBuffer equ -10h
            FP_Check_FileHashValue_CRC_hFile equ -14h
            FP_Check_FileHashValue_CRC_szFileName equ -(20h+MAX_PATH)

            push ebp
            mov ebp, esp
            sub esp, FP_Check_FileHashValue_CRC_StackSize

            push ebx
            push ecx
            push edx
            push esi
            push edi

            ;; clear the stack
            lea edi, [ebp-FP_Check_FileHashValue_CRC_StackSize]
            mov ecx, FP_Check_FileHashValue_CRC_StackSize
            xor eax, eax
            cld
            rep stosb

            mov ebx, dword ptr [ebp+FP_Check_FileHashValue_CRC_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            push MAX_PATH
            lea eax, [ebp+FP_Check_FileHashValue_CRC_szFileName]
            push eax
            push NULL
            call dword ptr [ebx].xGetModuleFileNameA

            push NULL
            push FILE_ATTRIBUTE_NORMAL
            push OPEN_EXISTING
            push NULL
            push FILE_SHARE_READ
            push GENERIC_READ
            lea eax, [ebp+FP_Check_FileHashValue_CRC_szFileName]
            push eax
            call dword ptr [ebx].xCreateFileA
            cmp eax, INVALID_HANDLE_VALUE
            jz NotFound_FP_Check_FileHashValue_CRC
            mov dword ptr [ebp+FP_Check_FileHashValue_CRC_hFile], eax

            push NULL
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_hFile]
            call dword ptr [ebx].xGetFileSize
            ;cmp eax, INVALID_FILE_SIZE
            ;jz NotFound_FP_Check_FileHashValue_CRC
            mov dword ptr [ebp+FP_Check_FileHashValue_CRC_fileSize], eax

            push PAGE_READWRITE
            push MEM_COMMIT
            push eax
            push NULL
            call dword ptr [ebx].xVirtualAlloc
            mov dword ptr [ebp+FP_Check_FileHashValue_CRC_pBuffer], eax

            ;; read file
            push NULL
            lea eax, [ebp+FP_Check_FileHashValue_CRC_NumberOfBytesRW]
            push eax
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_fileSize]
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_pBuffer]
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_hFile]
            call dword ptr [ebx].xReadFile

            push dword ptr [ebp+FP_Check_FileHashValue_CRC_hFile]
            call dword ptr [ebx].xCloseHandle

            ;; get CRC value
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_fileSize]
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_pBuffer]
            mov eax, dword ptr [ebp+FP_Check_FileHashValue_CRC_Arg_FuncAddr]
            assume eax : ptr FUNCADDRTBL
            call dword ptr [eax].xCRC32
            mov esi, eax

            ;; release the memory
            push MEM_RELEASE
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_fileSize]
            push dword ptr [ebp+FP_Check_FileHashValue_CRC_pBuffer]
            call dword ptr [ebx].xVirtualFree

            call Get_FP_Check_FileHashValue_CRC_Eip
            Get_FP_Check_FileHashValue_CRC_Eip:
            pop edi
            add edi, offset FP_Check_FileHashValue_Orig_CRC - offset Get_FP_Check_FileHashValue_CRC_Eip
            sub edi, esi
            jz NotFound_FP_Check_FileHashValue_CRC
            jmp Found_FP_Check_FileHashValue_CRC

            Exit_FP_Check_FileHashValue_CRC:
            pop edi
            pop esi
            pop edx
            pop ecx
            pop ebx
            assume eax : nothing
            assume ebx : nothing
            mov esp, ebp
            pop ebp
            retn 08h
            NotFound_FP_Check_FileHashValue_CRC:
            xor eax, eax
            jmp Exit_FP_Check_FileHashValue_CRC
            Found_FP_Check_FileHashValue_CRC:
            mov eax, 1
            jmp Exit_FP_Check_FileHashValue_CRC
            FP_Check_FileHashValue_Orig_CRC:
            dd 0
            End_FP_Check_FileHashValue_CRC:
            Windows NT系列平臺支持一個會話多個桌面,將線程的桌面交換到自己的桌面。
            目前還沒有有效的方法轉換到舊的桌面。

            AD_SwitchDesktop:
            AD_SwitchDesktop_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+AD_SwitchDesktop_Arg_Win32Api]

            push ebx
            push ecx
            push edx
            push edi
            push esi

            mov ebx, eax
            assume ebx : ptr WIN32APIBASE

            call dword ptr [ebx].xGetCurrentThreadId
            push eax
            call dword ptr [ebx].xGetThreadDesktop
            mov ecx, eax

            push DESKTOP_SWITCHDESKTOP
            push FALSE
            push 0
            call dword ptr [ebx].xOpenInputDesktop
            mov edx, eax

            push NULL
            push GENERIC_ALL
            push 0
            push NULL
            push NULL
            call AD_SwitchDesktop_Str
            db "MyDesktop",0
            AD_SwitchDesktop_Str:
            call dword ptr [ebx].xCreateDesktopA
            mov esi, eax

            push esi
            call dword ptr [ebx].xSetThreadDesktop

            push esi
            call dword ptr [ebx].xSwitchDesktop

            push 5000
            call dword ptr [ebx].xSleep

            push edx
            call dword ptr [ebx].xSwitchDesktop

            push ecx
            call dword ptr [ebx].xSetThreadDesktop

            push esi
            call dword ptr [ebx].xCloseDesktop

            mov eax, 1

            pop esi
            pop edi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            retn 04h
            End_AD_SwitchDesktop:
            BlockInput函數阻止了鼠標和鍵盤事件到達應用程序。

            AD_BlockInput:
            AD_BlockInput_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+AD_BlockInput_Arg_Win32Api]

            push ebx
            mov ebx, eax
            assume ebx : ptr WIN32APIBASE

            push TRUE
            call dword ptr [ebx].xBlockInput
            test eax, eax
            jz Exit_AD_BlockInput
            push 5000
            call dword ptr [ebx].xSleep

            push FALSE
            call dword ptr [ebx].xBlockInput
            xor eax, eax
            Exit_AD_BlockInput:
            pop ebx
            assume ebx : nothing
            retn 04h
            End_AD_BlockInput:
            利用Nativa API函數ZwSetInformationThread函數通過ThreadHideFromDebugger來達到隱藏調試器的目的

            AD_ZwSetInfomationThread:
            AD_ZwSetInfomationThread_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+AD_ZwSetInfomationThread_Arg_Win32Api]
            push ebx
            mov ebx, eax
            assume ebx : ptr WIN32APIBASE

            push 0
            push NULL
            push ThreadHideFromDebugger
            call dword ptr [ebx].xGetCurrentThread
            push eax
            call dword ptr [ebx].xZwSetInformationThread
            cmp eax, STATUS_SUCCESS
            Exit_AD_ZwSetInfomationThread:
            pop ebx
            assume ebx : nothing
            retn 04h
            End_AD_ZwSetInfomationThread:
            通過系統索引號調用NtSetInformationThread使用ThreadHideFromDebugger來達到隱藏調試器的目的

            AD_INT_2e:
            AD_INT_2e_Arg_Win32Api equ 08h
            AD_INT_2e_StackSize equ 10h + sizeof OSVERSIONINFOEX
            AD_INT_2e_bOsVersionInfoEx equ -04h
            AD_INT_2e_osvi equ -(10h+sizeof OSVERSIONINFOEX)
            push ebp
            mov ebp, esp
            sub esp, AD_INT_2e_StackSize

            push ebx
            push ecx
            push edx
            push edi
            push esi

            mov ebx, dword ptr [ebp+AD_INT_2e_Arg_Win32Api]
            assume ebx : ptr WIN32APIBASE

            lea edx, [ebp+AD_INT_2e_osvi]
            assume edx : ptr OSVERSIONINFOEX

            ;; clear the stack
            lea edi, [ebp-AD_INT_2e_StackSize]
            mov ecx, AD_INT_2e_StackSize
            xor eax, eax
            cld
            rep stosb

            push sizeof OSVERSIONINFOEX
            pop dword ptr [edx].dwOSVersionInfoSize

            call dword ptr [ebx].xGetCurrentThread
            mov esi, eax

            lea edx, [ebp+AD_INT_2e_osvi]
            push edx
            call dword ptr [ebx].xGetVersionExA
            test eax, eax
            jz Exit_AD_INT_2e
            ;; Test for the Windows NT product family
            lea edx, [ebp+AD_INT_2e_osvi]
            cmp dword ptr [edx].dwPlatformId, VER_PLATFORM_WIN32_NT
            jnz Exit_AD_INT_2e
            push 0
            push 0
            push ThreadHideFromDebugger
            push esi
            mov eax, 0EEh ; NtSetInformationThread
            mov edx, esp
            int 2eh
            add esp, 10h

            push 0
            push 0
            push ThreadHideFromDebugger
            push esi
            mov eax, 0E5h ; NtSetInformationThread
            mov edx, esp
            int 2eh
            add esp, 10h
            ;jmp Found_AD_INT_2e
            ;AD_INT_2e_Tmp1:
            ;; Test for the Windows 95 product family
            ;cmp dword ptr [edx].dwPlatformId, VER_PLATFORM_WIN32_WINDOWS
            ;jnz AD_INT_2e_Tmp2
            ;AD_INT_2e_Tmp2:
            ;; Microsoft Win32s
            Exit_AD_INT_2e:
            xor eax, eax
            pop esi
            pop edi
            pop edx
            pop ecx
            pop ebx
            assume ebx : nothing
            assume edx : nothing
            mov esp, ebp
            pop ebp
            retn 04h
            End_AD_INT_2e:
            Ollydbg傳遞用戶定義的數據給msvcrt的vsprintf函數,如果這些數據包含
            格式字符串標記.如果包換多個%s標記,這樣會指向一個無效的內存導致
            ollydbg失效。

            AS_OD_OutputDebugString:
            AS_OD_OutputDebugString_Arg_Win32Api equ 04h
            mov eax, dword ptr [esp+AS_OD_OutputDebugString_Arg_Win32Api]
            assume eax : ptr WIN32APIBASE
            call AS_OD_OutputDebugString_Str
            db "%s%s",0
            AS_OD_OutputDebugString_Str:
            call dword ptr [eax].xOutputDebugStringA
            xor eax, eax
            assume eax : nothing
            retn 04h
            End_AS_OD_OutputDebugString:
            通過觸發異常進入異常處理程序,將調試寄存器清0,清除斷點。
            Dr0,Dr1,Dr2,Dr3,Dr6和Dr7。Dr0-Dr3用作一般的線性地址,Dr6為調試狀態寄存器
            Dr7為調試控制寄存器。

            AB_HWP_CLR_Exception:
            call Get_AB_HWP_CLR_Exception_Eip
            Get_AB_HWP_CLR_Exception_Eip:
            pop eax
            add eax, offset AB_HWP_CLR_Exception_Exception - offset Get_AB_HWP_CLR_Exception_Eip
            push eax
            assume fs : nothing
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp
            xor eax, eax
            ;; throw an exception
            div eax
            ;; restore exception handler
            pop dword ptr fs:[0]
            add esp, 04h
            jmp Exit_AB_HWP_CLR_Exception
            AB_HWP_CLR_Exception_Exception:
            mov eax, dword ptr [esp+0ch]
            assume eax : ptr CONTEXT
            ;; clr debug registers context Dr0-Dr3
            mov dword ptr [eax].iDr0, 0
            mov dword ptr [eax].iDr1, 0
            mov dword ptr [eax].iDr2, 0
            mov dword ptr [eax].iDr3, 0
            mov dword ptr [eax].iDr6, 0
            mov dword ptr [eax].iDr7, 0
            ;; set eip upon return
            add dword ptr [eax].regEip, 02h
            xor eax, eax
            retn
            Exit_AB_HWP_CLR_Exception:
            xor eax, eax
            assume eax : nothing
            retn 0h
            End_AB_HWP_CLR_Exception:
            還有很多反調試的方法沒有歸結到上面,一開始想做的全些。但是后來發現,太多了。還是以后慢慢歸納吧。
            附件中的程序是一個可以添加反調試代碼到其他程序的一個小玩意。
            使用命令為AntiDebugger 1 2 3 4 file.exe 類似這樣 ^_^
            終于寫完了,累吖。。。:eek:

            玩命
            2008-08-21, 10:43
            附件的程序有三個選項沒有完成 驗證文件尺寸,文件CRC,內存CRC 這三個功能的填充原先值的代碼沒有完成。由于這期拖的時間有點長了。 為了敢時間就沒有寫填充原先值的功能。(比較麻煩,添加到目標程序ANTI函數是動態的所以。以后添加上)如果各位大大們有興趣可以利用提供的CRC函數補寫完這個功能。CRC函數的標號為xCRC可以到源文件中搜索下得到。:o:
            如果代碼中出現什么BUG之流的東東 請各位盡情指出咯。。。
            日韩精品久久无码人妻中文字幕| 国内精品久久久久久久久电影网| 午夜精品久久久久久中宇| 久久国产色AV免费看| 久久精品国产只有精品66| 久久精品中文字幕一区 | 国产产无码乱码精品久久鸭| 99久久99久久精品国产| 亚洲午夜久久久影院| 91精品国产色综久久| 亚洲精品乱码久久久久久自慰| 久久精品国产半推半就| 久久精品人人做人人爽电影 | 久久久久国产| 国产精品久久久天天影视| 久久婷婷色香五月综合激情| AAA级久久久精品无码区| 久久综合给合久久狠狠狠97色69| 日本精品久久久久影院日本| 亚洲国产精品久久久久| 97久久国产亚洲精品超碰热| 综合人妻久久一区二区精品| 无码乱码观看精品久久| 精品久久久久中文字幕一区| 久久国产精品久久| 国产亚洲综合久久系列| 亚洲精品乱码久久久久久自慰| 午夜精品久久久久| 亚洲伊人久久成综合人影院 | 91精品国产高清久久久久久国产嫩草| 久久永久免费人妻精品下载| 精产国品久久一二三产区区别| 亚洲午夜久久久| 亚洲第一永久AV网站久久精品男人的天堂AV | 久久久午夜精品福利内容| 久久久国产精华液| 久久久久久A亚洲欧洲AV冫| 亚洲国产精品久久66| 国产亚洲美女精品久久久| 久久精品成人欧美大片| 久久无码一区二区三区少妇|