| 关键词: nbsp eax dword Result mov exit IsDebug end ptr EXCEPTION |
//使用IsDebuggerPresent这个API来检测是否被调试function FD_IsDebuggerPresent(): Boolean;begin if IsDebuggerPresent then Result := True else Result := False;end; //使用查看PEB结构中标志位beingDegug来检测是否被调试function PD_PEB_BeingDebuggedFlag(): Boolean;begin asm mov @result, 0 mov eax, fs:[30h] //EAX = TEB.ProcessEnvironmentBlock add eax, 2 mov eax, [eax] and eax, $000000ff //AL = PEB.BeingDebugged test eax, eax jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end;end; //查看PEB结构中的NtGlobalFlags标志位来检测是否被调试function FD_PEB_NtGlobalFlags(): Boolean;begin asm mov @result, 0 mov eax, fs:[30h] mov eax, [eax+68h] and eax, $70 //NtGlobalFlags test eax, eax jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end;end; //在PEB结构中,使用HeapFlags来//检测调试器也不是非常可靠,但却很常用。//这个域由一组标志组成,正常情况下,该值应为2function FD_Heap_HeapFlags(): Boolean;begin asm mov @result, 0 mov eax, fs:[30h] mov eax, [eax+18h] //PEB.ProcessHeap mov eax, [eax+0ch] //PEB.ProcessHeap.Flags cmp eax, 2 jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end;end; //检测PEB结构中的标志位ForceFlags,它也由一//组标志组成,正常情况下,该值应为0function FD_Heap_ForceFlags(): Boolean;begin asm mov @result, 0 mov eax, fs:[30h] mov eax, [eax+18h] mov eax, [eax+10h] test eax, eax jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end;end; //使用API:CheckRemoteDebuggerPresentfunction FD_CheckRemoteDebuggerPresent(): Boolean;var Func_Addr: Pointer; hModule: Cardinal; pDebugBool: PBool;begin result := false; hModule := GetModuleHandle('kernel32.dll'); if hModule = INVALID_HANDLE_VALUE then exit; Func_addr := GetProcAddress(hModule, 'CheckRemoteDebuggerPresent'); if (Func_addr <> nil) then begin asm lea eax, pDebugBool push eax push $ffffffff call Func_addr cmp dword ptr[pDebugBool], 0 jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end; end;end; //使用ntdll_NtQueryInformationProcess()来查询//ProcessDebugPort可以用来检测反调试function FD_NtQueryInfoProc_DbgPort(): Boolean;var Func_Addr: Pointer; hModule: Cardinal; ReturnLength: PULONG; dwDebugPort: PDWORD;begin result := false; hModule := GetModuleHandle('ntdll.dll'); if hModule = INVALID_HANDLE_VALUE then exit; Func_addr := GetProcAddress(hModule, 'ZwQueryInformationProcess'); if (Func_addr <> nil) then begin asm lea eax, ReturnLength push eax //ReturnLength push 4 //ProcessInformationLength lea eax, dwDebugPort push eax //ProcessInformation push 7 //ProcessInformationClass push $FFFFFFFF //ProcessHandle call Func_addr //NtQueryInformationProcess cmp [dwDebugPort], 0 jne @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end; end;end; //查询winXp自动创建的"debug object"的句柄function FD_NtQueryInfoProc_DbgObjHandle(): Boolean;var Func_Addr: Pointer; hModule: Cardinal; ReturnLength: PULONG; dwDebugPort: PDWORD;begin result := false; hModule := GetModuleHandle('ntdll.dll'); if hModule = INVALID_HANDLE_VALUE then exit; Func_addr := GetProcAddress(hModule, 'ZwQueryInformationProcess'); if (Func_addr <> nil) then begin asm lea eax, ReturnLength push eax push 4 lea eax, dwDebugPort push eax push $1E push $FFFFFFFF call Func_addr mov eax, [dwDebugPort] test eax, eax jnz @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end; end;end; //查询winXp自动创建的"debug object",//未公开的ProcessDebugFlags类,当调试器存在时,它会返回falsefunction FD_NtQueryInfoProc_DbgFlags(): Boolean;var Func_Addr: Pointer; hModule: Cardinal; ReturnLength: PULONG; dwDebugPort: PDWORD;begin result := false; hModule := GetModuleHandle('ntdll.dll'); if hModule = INVALID_HANDLE_VALUE then exit; Func_addr := GetProcAddress(hModule, 'ZwQueryInformationProcess'); if (Func_addr <> nil) then begin asm lea eax, ReturnLength push eax push 4 lea eax, dwDebugPort push eax push $1F push $FFFFFFFF call Func_addr mov eax, [dwDebugPort] test eax, eax jz @IsDebug jmp @exit @IsDebug: mov @result, 1 @exit: end; end;end; //是否获得SeDebugPrivilege//是否可以使用openprocess操作CSRSS.EXEfunction FD_SeDebugPrivilege(csrssPid: THandle): Boolean;var hTmp: Cardinal;begin result := False; hTmp := OpenProcess(PROCESS_ALL_ACCESS,false,csrssPid); if hTmp <> 0 then begin CloseHandle (hTmp); result := true; end;end; //查找已知的调试器的窗口来检测是否被调试function FD_Find_Debugger_Window(): Boolean;var whWnd: DWORD;begin result := True; //ollydbg v1.1 whWnd := FindWindow('icu_dbg', nil); if whWnd <> 0 then Exit; //ollyice pe--diy whWnd := FindWindow('pe--diy', nil); if whWnd <> 0 then Exit; //ollydbg ?- whWnd := FindWindow('ollydbg', nil); if whWnd <> 0 then Exit; //windbg whWnd := FindWindow('WinDbgFrameClass', nil); if whWnd <> 0 then Exit; //dede3.50 whWnd := FindWindow('TDeDeMainForm', nil); if whWnd <> 0 then Exit; //IDA5.20 whWnd := FindWindow('TIdaWindow', nil); if whWnd <> 0 then Exit; result := False;end; //给CloseHandle()函数一个无效句柄作为输入参数//是否触发一个EXCEPTION_INVALID_HANDLE (0xc0000008)的异常function FD_Exception_Closehandle(): Boolean;begin try CloseHandle($00001234); result := False; except Result := True; end;end; //int3 检测function FD_Exception_Int3(): Boolean;begin asm mov @result, 0 push offset @exception_handler //set exception handler push dword ptr fs:[0h] mov dword ptr fs:[0h],esp xor eax,eax //reset EAX invoke int3 int 3h pop dword ptr fs:[0h] //restore exception handler add esp,4 test eax,eax // check the flag je @IsDebug jmp @exit @exception_handler: mov eax,dword ptr [esp+$c]//EAX = ContextRecord mov dword ptr [eax+$b0],$ffffffff//set flag (ContextRecord.EAX) inc dword ptr [eax+$b8]//set ContextRecord.EIP xor eax,eax ret @IsDebug: xor eax,eax inc eax mov esp,ebp pop ebp ret @exit: xor eax,eax mov esp,ebp pop ebp ret end;end; //使用OutputDebugString函数来检测function FD_OutputDebugString(): boolean;var tmpD: DWORD;begin OutputDebugString(''); tmpD := GetLastError; if(tmpD = 0) then result := true else Result := false;end; //检测STARTUPINFO结构中的值是否为0function FD_Check_StartupInfo(): Boolean;var si: STARTUPINFO;begin ZeroMemory(@si, sizeof(si)); si.cb := sizeof(si); GetStartupInfo(si); if (si.dwX <> 0) and (si.dwY <> 0) and (si.dwXCountChars <> 0) and (si.dwYCountChars <> 0) and (si.dwFillAttribute <> 0) and (si.dwXSize <> 0) and (si.dwYSize <> 0) then begin result := true end else result := false;end; //使用int 2dh中断的异常检测function FD_INT_2d(): Boolean;begin try asm int 2dh inc eax //any opcode of singlebyte. //;or u can put some junkcode, //"0xc8"..."0xc2"..."0xe8"..."0xe9" mov @result, 1 end; except Result := false; end;end; //最近比较牛的反调试function FS_OD_Int3_Pushfd(): Boolean;begin asm push offset @e_handler //set exception handler push dword ptr fs:[0h] mov dword ptr fs:[0h],esp xor eax,eax //reset EAX invoke int3 int 3h pushfd nop nop nop nop pop dword ptr fs:[0h] //restore exception handler add esp,4 test eax,eax //check the flag je @IsDebug jmp @Exit @e_handler: push offset @e_handler1 //set exception handler push dword ptr fs:[0h] mov dword ptr fs:[0h],esp xor eax,eax //reset EAX invoke int3 int 3h nop pop dword ptr fs:[0h] //restore exception handler add esp,4 //EAX = ContextRecord mov ebx,eax //dr0=>ebx mov eax,dword ptr [esp+$c] //set ContextRecord.EIP inc dword ptr [eax+$b8] mov dword ptr [eax+$b0],ebx //dr0=>eax xor eax,eax ret @e_handler1: //EAX = ContextRecord mov eax,dword ptr [esp+$c] //set ContextRecord.EIP inc dword ptr [eax+$b8] mov ebx,dword ptr[eax+$04] mov dword ptr [eax+$b0],ebx //dr0=>eax xor eax,eax ret @IsDebug: mov @result, 1 mov esp,ebp pop ebp ret @Exit: mov esp,ebp pop ebp ret end;end; //使用int1的异常检测来反调试function FS_SI_Exception_Int1(): Boolean;begin asm mov @result, 0 push offset @eh_int1 //set exception handler push dword ptr fs:[0h] mov dword ptr fs:[0h],esp xor eax,eax //reset flag(EAX) invoke int3 int 1h pop dword ptr fs:[0h] //restore exception handler add esp,4 test eax, eax // check the flag je @IsDebug jmp @Exit @eh_int1: mov eax,[esp+$4] mov ebx,dword ptr [eax] mov eax,dword ptr [esp+$c] //EAX = ContextRecord mov dword ptr [eax+$b0],1 //set flag (ContextRecord.EAX) inc dword ptr [eax+$b8] //set ContextRecord.EIP inc dword ptr [eax+$b8] //set ContextRecord.EIP xor eax, eax ret @IsDebug: mov @result, 1 mov esp,ebp pop ebp ret @Exit: xor eax, eax mov esp,ebp pop ebp ret end;end; //在异常处理过程中检测硬件断点function FB_HWBP_Exception(): Boolean;begin asm push offset @exeception_handler //set exception handler push dword ptr fs:[0h] mov dword ptr fs:[0h],esp xor eax,eax //reset EAX invoke int3 int 1h pop dword ptr fs:[0h] //restore exception handler add esp,4 //test if EAX was updated (breakpoint identified) test eax,eax jnz @IsDebug jmp @Exit @exeception_handler: //EAX = CONTEXT record mov eax,dword ptr [esp+$c] //check if Debug Registers Context.Dr0-Dr3 is not zero cmp dword ptr [eax+$04],0 jne @hardware_bp_found cmp dword ptr [eax+$08],0 jne @hardware_bp_found cmp dword ptr [eax+$0c],0 jne @hardware_bp_found cmp dword ptr [eax+$10],0 jne @hardware_bp_found jmp @exception_ret @hardware_bp_found: //set Context.EAX to signal breakpoint found mov dword ptr [eax+$b0],$FFFFFFFF @exception_ret: //set Context.EIP upon return inc dword ptr [eax+$b8] //set ContextRecord.EIP inc dword ptr [eax+$b8] //set ContextRecord.EIP xor eax,eax ret @IsDebug: mov @result, 1 mov esp,ebp pop ebp ret @Exit: xor eax, eax mov esp,ebp pop ebp ret end;end; |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|