首页 网络安全 安全学院 查看内容

Delphi 19种反调试检测法

2009-6-28 10:57 632 0

摘要: //使用IsDebuggerPresent这个API来检测是否被调试function FD_IsDebuggerPresent(): Boolean;begin  if IsDebugger...
关键词: 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;  
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部