//使用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来 //检测调试器也不是非常可靠,但却很常用。 //这个域由一组标志组成,正常情况下,该值应为2 function 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,它也由一 //组标志组成,正常情况下,该值应为0 function 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:CheckRemoteDebuggerPresent function 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类,当调试器存在时,它会返回false function 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.EXE function 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结构中的值是否为0 function 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;
|
请发表评论