zoukankan      html  css  js  c++  java
  • Delphi 19种反调试检测法

    //使用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;

  • 相关阅读:
    boost::asio在VS2008下的编译错误
    Java集合框架——接口
    ACM POJ 3981 字符串替换(简单题)
    ACM HDU 1042 N!(高精度计算阶乘)
    OneTwoThree (Uva)
    ACM POJ 3979 分数加减法(水题)
    ACM HDU 4004 The Frog's Games(2011ACM大连赛区第四题)
    Hexadecimal View (2011ACM亚洲大连赛区现场赛D题)
    ACM HDU 4002 Find the maximum(2011年大连赛区网络赛第二题)
    ACM HDU 4001 To Miss Our Children Time (2011ACM大连赛区网络赛)
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/3391273.html
Copyright © 2011-2022 走看看