zoukankan      html  css  js  c++  java
  • delphi 反调试代码汇总

    View Code
      1 unit Anti_Debug;
      2 
      3 interface
      4 
      5 uses
      6   Windows, SysUtils, Classes, TlHelp32;
      7 // -------------------查找-通用调试器(FD_)-----------------------------------
      8 function FD_IsDebuggerPresent(): Boolean; //  9 function PD_PEB_BeingDebuggedFlag(): Boolean; // 10 function FD_PEB_NtGlobalFlags(): Boolean; // 11 function FD_Heap_HeapFlags(): Boolean; // 12 function FD_Heap_ForceFlags(): Boolean; // 13 function FD_HEap_Tail(): Boolean; // √x
     14 function FD_CheckRemoteDebuggerPresent(): Boolean; // 15 function FD_NtQueryInfoProc_DbgPort(): Boolean; // 16 function FD_NtQueryInfoProc_DbgObjHandle(): Boolean; // 17 function FD_NtQueryInfoProc_DbgFlags(): Boolean; // 18 { function FD_NtQueryInfoProc_SysKrlDbgInfo():boolean; //× }
     19 function FD_SeDebugPrivilege(csrssPid: THandle): Boolean; // 20 { function FD_Parent_Process();//× }
     21 function FD_DebugObject_NtQueryObject(): Boolean;
     22 function FD_Find_Debugger_Window(): Boolean; // 23 function FD_Find_Debugger_Process(): Boolean;
     24 { function FD_Find_Device_Driver():boolean; //× }
     25 function FD_Exception_Closehandle(): Boolean; // 26 function FD_Exception_Int3(): Boolean; // 27 { function FD_Exception_Popf():boolean; //√ }
     28 function FD_OutputDebugString(): Boolean; // 29 { function FD_TEB_check_in_Vista():boolean;//× }
     30 function FD_Check_StartupInfo(): Boolean; // 31 { function Parent_Process1():boolean; //× }
     32 { function Exception_Instruction_count():boolean; //× }
     33 function FD_INT_2d(): Boolean; // 34 // -----------------检测-专用调试器(FS_)-------------------------------------
     35 function FS_OD_Int3_Pushfd(): Boolean; // 36 { function FS_SI_UnhandledExceptionFilter(): Boolean; //× }
     37 { function FS_ODP_Process32NextW(): Boolean;  //× }
     38 { function FS_ODP_OutputDebugStringA(): Boolean; //× }
     39 { function FS_ODP_OpenProcess(): Boolean;   //× }
     40 { function FS_ODP_CheckRemoteDebuggerPresent(): Boolean; //× }
     41 { function FS_ODP_ZwSetInformationThread(): Boolean;  //× }
     42 
     43 function FS_SI_Exception_Int1(): Boolean; // 44 { function FS_OD_Exception_GuardPages(): Boolean;  //× }
     45 
     46 function IsInsideVMWare(): Boolean;
     47 function IsRunInVPC(out ErrMsg: string): Boolean;
     48 function FV_VMWare_VMX(): Boolean;
     49 function FV_VPC_Exception(): Boolean;
     50 { function FV_VME_RedPill():Integer;//0:none,1:vmvare;2:vpc;3:others  //× }
     51 // -------------检测-断点(FB_)----------------------------------------------
     52 function FB_HWBP_Exception(): Boolean; // 53 { function FB_SWBP_Memory_CRC():DWORD; //× }
     54 { function FB_SWBP_ScanCC(BYTE * addr,int len):Boolean;//× }
     55 { function FB_SWBP_CheckSum_Thread(BYTE *addr_begin,BYTE *addr_end,DWORD sumValue):Boolean;//× }
     56 // --------------检测-跟踪(FT_)----------------------------------------------
     57 { //Find Single-Step or Trace
     58   function FT_PushSS_PopSS():Boolean;
     59   procedure  FT_RDTSC(time:LongWord ); //unsigned int * time
     60   function FT_GetTickCount():DWORD;
     61   function FT_SharedUserData_TickCount():DWORD;
     62   function FT_timeGetTime():DWORD;
     63   function FT_QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount):Int64;
     64   function FT_F1_IceBreakpoint():Boolean;
     65   function FT_Prefetch_queue_nop1():Boolean;
     66   function FT_Prefetch_queue_nop2():Boolean;
     67 }
     68 // -----------------检测-补丁(FP_)----------------------------------------------
     69 { function FP_Check_FileSize( Size:DWORD):Boolean;
     70   function FP_Check_FileHashValue_CRC( CRCVALUE_origin:DWORD):Boolean;
     71   function FP_Check_FileHashValue_MD5( MD5VALUE_origin:DWORD):Boolean;
     72 }
     73 // -----------------------------------------------------------------------------
     74 function TestDebug(var Mssg: AnsiString): Integer;
     75 
     76 implementation
     77 
     78 function TestDebug(var Mssg: AnsiString): Integer;
     79 var
     80   isdebugged: DWORD;
     81   ts: TStringList;
     82 label
     83   IsDebug;
     84 begin
     85   ts := TStringList.Create;
     86   try
     87     try
     88       // 反调试检测
     89       isdebugged := 0;
     90       if FB_HWBP_Exception then
     91       begin
     92         isdebugged := isdebugged + 1;
     93         ts.Add('FB_HWBP_Exception');
     94       end;
     95       if FS_SI_Exception_Int1 then
     96       begin
     97         isdebugged := isdebugged + 1;
     98         ts.Add('FS_SI_Exception_Int1');
     99       end;
    100       if FD_Find_Debugger_Window then
    101       begin
    102         isdebugged := isdebugged + 1;
    103         ts.Add('FD_Find_Debugger_Window');
    104       end;
    105       if FD_IsDebuggerPresent then
    106       begin
    107         isdebugged := isdebugged + 1;
    108         ts.Add('FD_IsDebuggerPresent');
    109       end;
    110       if PD_PEB_BeingDebuggedFlag then
    111       begin
    112         isdebugged := isdebugged + 1;
    113         ts.Add('PD_PEB_BeingDebuggedFlag');
    114       end;
    115       if FD_PEB_NtGlobalFlags then
    116       begin
    117         isdebugged := isdebugged + 1;
    118         ts.Add('FD_PEB_NtGlobalFlags');
    119       end;
    120       if FD_Heap_HeapFlags then
    121       begin
    122         isdebugged := isdebugged + 1;
    123         ts.Add('FD_Heap_HeapFlags');
    124       end;
    125       if FD_CheckRemoteDebuggerPresent then
    126       begin
    127         isdebugged := isdebugged + 1;
    128         ts.Add('FD_CheckRemoteDebuggerPresent');
    129       end;
    130       if FD_NtQueryInfoProc_DbgPort then
    131       begin
    132         isdebugged := isdebugged + 1;
    133         ts.Add('FD_NtQueryInfoProc_DbgPort');
    134       end;
    135       if FD_NtQueryInfoProc_DbgObjHandle then
    136       begin
    137         isdebugged := isdebugged + 1;
    138         ts.Add('FD_NtQueryInfoProc_DbgObjHandle');
    139       end;
    140       if FD_NtQueryInfoProc_DbgFlags then
    141       begin
    142         isdebugged := isdebugged + 1;
    143         ts.Add('FD_NtQueryInfoProc_DbgFlags');
    144       end;
    145       if FD_SeDebugPrivilege(916) then
    146       begin
    147         isdebugged := isdebugged + 1;
    148         ts.Add('FD_SeDebugPrivilege');
    149       end;
    150       if FD_Exception_Closehandle then
    151       begin
    152         isdebugged := isdebugged + 1;
    153         ts.Add('FD_Exception_Closehandle');
    154       end;
    155       if FD_Exception_Int3 then
    156       begin
    157         isdebugged := isdebugged + 1;
    158         ts.Add('FD_Exception_Int3');
    159       end;
    160       if FD_OutputDebugString then
    161       begin
    162         isdebugged := isdebugged + 1;
    163         ts.Add('FD_OutputDebugString');
    164       end;
    165       if FD_Check_StartupInfo then
    166       begin
    167         isdebugged := isdebugged + 1;
    168         ts.Add('FD_Check_StartupInfo');
    169       end;
    170       if FD_INT_2d then
    171       begin
    172         isdebugged := isdebugged + 1;
    173         ts.Add('FD_INT_2d');
    174       end;
    175       if FS_OD_Int3_Pushfd then
    176       begin
    177         isdebugged := isdebugged + 1;
    178         ts.Add('FS_OD_Int3_Pushfd');
    179       end;
    180       // if FD_DebugObject_NtQueryObject then begin isdebugged := isdebugged + 1; ts.Add('FD_DebugObject_NtQueryObject'); end;
    181 
    182     IsDebug:
    183       if isdebugged > 0 then
    184       begin
    185         Result := isdebugged;
    186         Mssg := ts.Text;
    187       end
    188       else
    189         Mssg := '正常执行!';
    190     except
    191       on e: Exception do
    192         Mssg := ('发生错误!' + #10#13 + e.Message);
    193     end;
    194   finally
    195     ts.Free;
    196   end;
    197 end;
    198 
    199 // 使用IsDebuggerPresent这个API来检测是否被调试
    200 function FD_IsDebuggerPresent(): Boolean;
    201 var
    202   isDebuggerPresent: function: Boolean;
    203   DllModule: THandle;
    204 begin
    205   DllModule := LoadLibrary('kernel32.dll');
    206   isDebuggerPresent := GetProcAddress(DllModule, 'IsDebuggerPresent');
    207   Result := isDebuggerPresent;
    208 end;
    209 
    210 // 使用查看PEB结构中标志位beingDegug来检测是否被调试
    211 function PD_PEB_BeingDebuggedFlag(): Boolean;
    212 begin
    213   asm
    214     mov @result, 0
    215     mov eax, fs:[30h]   // EAX = TEB.ProcessEnvironmentBlock
    216     add eax, 2
    217     mov eax, [eax]
    218     and eax, $000000ff // AL = PEB.BeingDebugged
    219     test eax, eax
    220     jne @IsDebug
    221     jmp @exit
    222   @IsDebug:
    223     mov @result, 1
    224   @exit:
    225   end;
    226 end;
    227 
    228 // 查看PEB结构中的NtGlobalFlags标志位来检测是否被调试
    229 function FD_PEB_NtGlobalFlags(): Boolean;
    230 begin
    231   asm
    232     mov @result, 0
    233     mov eax, fs:[30h]
    234     mov eax, [eax+68h]
    235     and eax, $70       // NtGlobalFlags
    236     test eax, eax
    237     jne @IsDebug
    238     jmp @exit
    239   @IsDebug:
    240     mov @result, 1
    241   @exit:
    242   end;
    243 end;
    244 
    245 // 在PEB结构中,使用HeapFlags来
    246 // 检测调试器也不是非常可靠,但却很常用。
    247 // 这个域由一组标志组成,正常情况下,该值应为2
    248 function FD_Heap_HeapFlags(): Boolean;
    249 begin
    250   asm
    251     mov @result, 0
    252     mov eax, fs:[30h]
    253     mov eax, [eax+18h] // PEB.ProcessHeap
    254     mov eax, [eax+0ch] // PEB.ProcessHeap.Flags
    255     cmp eax, 2
    256     jne @IsDebug
    257     jmp @exit
    258   @IsDebug:
    259     mov @result, 1
    260   @exit:
    261   end;
    262 end;
    263 
    264 // 检测PEB结构中的标志位ForceFlags,它也由一
    265 // 组标志组成,正常情况下,该值应为0
    266 function FD_Heap_ForceFlags(): Boolean;
    267 begin
    268   asm
    269     mov @result, 0
    270     mov eax, fs:[30h]
    271     mov eax, [eax+18h]        mov eax, [eax+10h]
    272     test eax, eax
    273     jne @IsDebug
    274     jmp @exit
    275   @IsDebug:
    276     mov @result, 1
    277   @exit:
    278   end;
    279 end;
    280 
    281 function FD_HEap_Tail(): Boolean;
    282 begin {
    283     asm
    284     mov @result, 0
    285     //get unused_bytes
    286     movzx ecx,Byte ptr[eax - 2]
    287     movzx edx,word ptr[eax - 8] //size
    288     sub eax,ecx
    289     lea  edi,[edx*8 + eax]
    290     mov al,0abh
    291     mov cl,8
    292     repe sca** //ppansichar   ?
    293     je @IsDebug
    294     jmp @Exit
    295     @IsDebug:
    296     mov @result,1
    297     @exit:
    298     end; }
    299 end;
    300 
    301 // 使用API:CheckRemoteDebuggerPresent
    302 function FD_CheckRemoteDebuggerPresent(): Boolean;
    303 var
    304   Func_Addr: Pointer;
    305   hModule: Cardinal;
    306   pDebugBool: PBool;
    307 begin
    308   Result := false;
    309   hModule := GetModuleHandle('kernel32.dll');
    310   if hModule = INVALID_HANDLE_VALUE then
    311     exit;
    312   Func_Addr := GetProcAddress(hModule, 'CheckRemoteDebuggerPresent');
    313   if (Func_Addr <> nil) then
    314   begin
    315     asm
    316       lea eax, pDebugBool
    317       push eax
    318       push $ffffffff
    319       call Func_addr
    320       cmp dword ptr[pDebugBool], 0
    321       jne @IsDebug
    322       jmp @exit
    323     @IsDebug:
    324       mov @result, 1
    325     @exit:
    326     end;
    327   end;
    328 end;
    329 
    330 // 使用ntdll_NtQueryInformationProcess()来查询
    331 // ProcessDebugPort可以用来检测反调试
    332 function FD_NtQueryInfoProc_DbgPort(): Boolean;
    333 var
    334   Func_Addr: Pointer;
    335   hModule: Cardinal;
    336   ReturnLength: PULONG;
    337   dwDebugPort: PDWORD;
    338 begin
    339   Result := false;
    340   hModule := GetModuleHandle('ntdll.dll');
    341   if hModule = INVALID_HANDLE_VALUE then
    342     exit;
    343   Func_Addr := GetProcAddress(hModule, 'ZwQueryInformationProcess');
    344   if (Func_Addr <> nil) then
    345   begin
    346     asm
    347       lea eax, ReturnLength
    348       push eax                     // ReturnLength
    349       push 4                       // ProcessInformationLength
    350       lea eax, dwDebugPort
    351       push eax                     // ProcessInformation
    352       push 7                       // ProcessInformationClass
    353       push $FFFFFFFF               // ProcessHandle
    354       call Func_addr               // NtQueryInformationProcess
    355       cmp [dwDebugPort], 0
    356       jne @IsDebug
    357       jmp @exit
    358     @IsDebug:
    359       mov @result, 1
    360     @exit:
    361     end;
    362   end;
    363 end;
    364 
    365 // 查询winXp自动创建的"debug object"的句柄
    366 function FD_NtQueryInfoProc_DbgObjHandle(): Boolean;
    367 var
    368   Func_Addr: Pointer;
    369   hModule: Cardinal;
    370   ReturnLength: PULONG;
    371   dwDebugPort: PDWORD;
    372 begin
    373   Result := false;
    374   hModule := GetModuleHandle('ntdll.dll');
    375   if hModule = INVALID_HANDLE_VALUE then
    376     exit;
    377   Func_Addr := GetProcAddress(hModule, 'ZwQueryInformationProcess');
    378   if (Func_Addr <> nil) then
    379   begin
    380     asm
    381       lea eax, ReturnLength
    382       push eax
    383       push 4
    384       lea eax, dwDebugPort
    385       push eax
    386       push $1E
    387       push $FFFFFFFF
    388       call Func_addr
    389       mov eax, [dwDebugPort]
    390       test eax, eax
    391       jnz @IsDebug
    392       jmp @exit
    393     @IsDebug:
    394       mov @result, 1
    395     @exit:
    396     end;
    397   end;
    398 end;
    399 
    400 // 查询winXp自动创建的"debug object",
    401 // 未公开的ProcessDebugFlags类,当调试器存在时,它会返回false
    402 function FD_NtQueryInfoProc_DbgFlags(): Boolean;
    403 var
    404   Func_Addr: Pointer;
    405   hModule: Cardinal;
    406   ReturnLength: PULONG;
    407   dwDebugPort: PDWORD;
    408 begin
    409   Result := false;
    410   hModule := GetModuleHandle('ntdll.dll');
    411   if hModule = INVALID_HANDLE_VALUE then
    412     exit;
    413   Func_Addr := GetProcAddress(hModule, 'ZwQueryInformationProcess');
    414   if (Func_Addr <> nil) then
    415   begin
    416     asm
    417       lea eax, ReturnLength
    418       push eax
    419       push 4
    420       lea eax, dwDebugPort
    421       push eax
    422       push $1F
    423       push $FFFFFFFF
    424       call Func_addr
    425       mov eax, [dwDebugPort]
    426       test eax, eax
    427       jz @IsDebug
    428       jmp @exit
    429     @IsDebug:
    430       mov @result, 1
    431     @exit:
    432     end;
    433   end;
    434 end;
    435 
    436 // 是否获得SeDebugPrivilege
    437 // 是否可以使用openprocess操作CSRSS.EXE
    438 function FD_SeDebugPrivilege(csrssPid: THandle): Boolean;
    439 var
    440   hTmp: Cardinal;
    441 begin
    442   Result := false;
    443   hTmp := OpenProcess(PROCESS_ALL_ACCESS, false, csrssPid);
    444   if hTmp <> 0 then
    445   begin
    446     CloseHandle(hTmp);
    447     Result := true;
    448   end;
    449 end;
    450 
    451 function FD_DebugObject_NtQueryObject(): Boolean;
    452 const
    453   szdbgobj: array [0 .. 24] of AnsiChar = (chr($44), chr($00), chr($65), chr($00), chr($62),
    454     chr($00), chr($75), chr($00), chr($67), chr($00), chr($4F), chr($00), chr($62), chr($00),
    455     chr($6A), chr($00), chr($65), chr($00), chr($63), chr($00), chr($74), chr($00), chr($00),
    456     chr($00), chr($00));
    457 var
    458   hModule: Cardinal;
    459   Func_Addr: Pointer;
    460   psz: PAnsiChar;
    461 begin
    462   psz^ := szdbgobj[0];
    463   hModule := GetModuleHandle('ntdll.dll');
    464   if hModule = INVALID_HANDLE_VALUE then
    465     exit;
    466   Func_Addr := GetProcAddress(hModule, 'NtQueryObject');
    467   if Func_Addr = nil then
    468     exit;
    469   asm
    470     xor ebx,ebx
    471     push ebx
    472     push esp
    473     push ebx
    474     push ebx
    475     push 3
    476     push ebx
    477     Call dword ptr[Func_addr]
    478     pop edi
    479     push 4
    480     push $1000
    481     push edi
    482     push ebx
    483     call dword ptr[VirtualAlloc]
    484     push ebx
    485     push edi
    486     push eax
    487     push 3
    488     push ebx
    489     xchg esi,eax
    490     call dword ptr[Func_addr]
    491     lodsd
    492     xchg ecx,eax
    493   @label1:
    494     lodsd
    495     movzx edx,ax
    496     lodsd
    497     xchg esi,eax
    498     cmp edx,$16
    499     jne @lable2
    500     xchg ecx,edx
    501     mov edi,psz
    502     repe cmpsw  // repe cmp**
    503     xchg ecx,edx
    504     jne @lable2
    505     cmp dword ptr[eax],edx
    506     jne @IsDebug
    507   @lable2:
    508     add esi,edx
    509     and esi,-4
    510     lodsd
    511     loop @label1
    512   @IsDebug:
    513     mov  result, 1
    514   end;
    515 end;
    516 
    517 // 查找已知的调试器的窗口来检测是否被调试
    518 function FD_Find_Debugger_Window(): Boolean;
    519 var
    520   whWnd: DWORD;
    521 begin
    522   Result := true;
    523   // ollydbg v1.1
    524   whWnd := FindWindow('icu_dbg', nil);
    525   if whWnd <> 0 then
    526     exit;
    527   // ollyice pe--diy
    528   whWnd := FindWindow('pe--diy', nil);
    529   if whWnd <> 0 then
    530     exit;
    531   // ollydbg ?-
    532   whWnd := FindWindow('ollydbg', nil);
    533   if whWnd <> 0 then
    534     exit;
    535   // windbg
    536   whWnd := FindWindow('WinDbgFrameClass', nil);
    537   if whWnd <> 0 then
    538     exit;
    539   // dede3.50
    540   whWnd := FindWindow('TDeDeMainForm', nil);
    541   if whWnd <> 0 then
    542     exit;
    543   // IDA5.20
    544   whWnd := FindWindow('TIdaWindow', nil);
    545   if whWnd <> 0 then
    546     exit;
    547   Result := false;
    548 end;
    549 
    550 // 进程查看,是否有
    551 function FD_Find_Debugger_Process(): Boolean;
    552 var
    553   hSnapshort: THandle;
    554   pe32: TProcessEntry32;
    555   fName: AnsiString;
    556 begin
    557   Result := false;
    558   pe32.dwSize := SizeOf(pe32);
    559   hSnapshort := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    560   if (Process32First(hSnapshort, pe32)) then
    561   begin
    562     while Process32Next(hSnapshort, pe32) do
    563     begin
    564       begin
    565         fName := ExtractFileName(pe32.szExeFile);
    566         fName := UpperCase(fName);
    567 
    568         if StrComp(@fName[1], 'OLLYICE.EXE') = 0 then
    569         begin
    570           Result := true;
    571           exit;
    572         end;
    573         if StrComp(@fName[1], 'IDAG.EXE') = 0 then
    574         begin
    575           Result := true;
    576           exit;
    577         end;
    578         if StrComp(@fName[1], 'OLLYDBG.EXE') = 0 then
    579         begin
    580           Result := true;
    581           exit;
    582         end;
    583         if StrComp(@fName[1], 'PEID.EXE') = 0 then
    584         begin
    585           Result := true;
    586           exit;
    587         end;
    588         if StrComp(@fName[1], 'SOFTICE.EXE') = 0 then
    589         begin
    590           Result := true;
    591           exit;
    592         end;
    593         if StrComp(@fName[1], 'LORDPE.EXE') = 0 then
    594         begin
    595           Result := true;
    596           exit;
    597         end;
    598         if StrComp(@fName[1], 'IMPORTREC.EXE') = 0 then
    599         begin
    600           Result := true;
    601           exit;
    602         end;
    603         if StrComp(@fName[1], 'W32DSM89.EXE') = 0 then
    604         begin
    605           Result := true;
    606           exit;
    607         end;
    608         if StrComp(@fName[1], 'WINDBG.EXE') = 0 then
    609         begin
    610           Result := true;
    611           exit;
    612         end;
    613       end;
    614     end;
    615   end;
    616 end;
    617 
    618 // 给CloseHandle()函数一个无效句柄作为输入参数
    619 // 是否触发一个EXCEPTION_INVALID_HANDLE (0xc0000008)的异常
    620 function FD_Exception_Closehandle(): Boolean;
    621 begin
    622   try
    623     CloseHandle($00001234);
    624     Result := false;
    625   except
    626     Result := true;
    627   end;
    628 end;
    629 
    630 // int3 检测
    631 function FD_Exception_Int3(): Boolean;
    632 begin
    633   asm
    634     mov @result, 0
    635     push offset @exception_handler // set exception handler
    636     push dword ptr fs:[0h]
    637     mov dword ptr fs:[0h],esp
    638     xor eax,eax        // reset EAX invoke int3
    639     int 3h
    640     pop dword ptr fs:[0h] // restore exception handler
    641     add esp,4
    642     test eax,eax // check the flag
    643     je @IsDebug
    644     jmp @exit
    645   @exception_handler:
    646     mov eax,dword ptr [esp+$c]// EAX = ContextRecord
    647     mov dword ptr [eax+$b0],$ffffffff// set flag (ContextRecord.EAX)
    648     inc dword ptr [eax+$b8]// set ContextRecord.EIP
    649     xor eax,eax
    650     ret
    651   @IsDebug:
    652     xor eax,eax
    653     inc eax
    654     mov esp,ebp
    655     pop ebp
    656     ret
    657   @exit:
    658     xor eax,eax
    659     mov esp,ebp
    660     pop ebp
    661     ret
    662   end;
    663 end;
    664 
    665 // 使用OutputDebugString函数来检测
    666 function FD_OutputDebugString(): Boolean;
    667 var
    668   tmpD: DWORD;
    669 begin
    670   OutputDebugString('');
    671   tmpD := GetLastError;
    672   if (tmpD = 0) then
    673     Result := true
    674   else
    675     Result := false;
    676 end;
    677 
    678 // 检测STARTUPINFO结构中的值是否为0
    679 function FD_Check_StartupInfo(): Boolean;
    680 var
    681   si: STARTUPINFO;
    682 begin
    683   ZeroMemory(@si, SizeOf(si));
    684   si.cb := SizeOf(si);
    685   GetStartupInfo(si);
    686   if (si.dwX <> 0) and (si.dwY <> 0) and (si.dwXCountChars <> 0) and (si.dwYCountChars <> 0) and
    687     (si.dwFillAttribute <> 0) and (si.dwXSize <> 0) and (si.dwYSize <> 0) then
    688   begin
    689     Result := true
    690   end
    691   else
    692     Result := false;
    693 end;
    694 
    695 // 使用int 2dh中断的异常检测
    696 function FD_INT_2d(): Boolean;
    697 begin
    698   try
    699     asm
    700       int 2dh
    701       inc eax // any opcode of singlebyte.
    702       // ;or u can put some junkcode,
    703       // "0xc8"..."0xc2"..."0xe8"..."0xe9"
    704       mov @result, 1
    705     end;
    706   except
    707     Result := false;
    708   end;
    709 end;
    710 
    711 // 最近比较牛的反调试
    712 function FS_OD_Int3_Pushfd(): Boolean;
    713 begin
    714   asm
    715     push offset @e_handler // set exception handler
    716     push dword ptr fs:[0h]
    717     mov dword ptr fs:[0h],esp
    718     xor eax,eax // reset EAX invoke int3
    719     int 3h
    720     pushfd
    721     nop
    722     nop
    723     nop
    724     nop
    725     pop dword ptr fs:[0h]   // restore exception handler
    726     add esp,4
    727 
    728     test eax,eax   // check the flag
    729     je @IsDebug
    730     jmp @Exit
    731 
    732   @e_handler:
    733     push offset @e_handler1   // set exception handler
    734     push dword ptr fs:[0h]
    735     mov dword ptr fs:[0h],esp
    736     xor eax,eax   // reset EAX invoke int3
    737     int 3h
    738     nop
    739     pop dword ptr fs:[0h]   // restore exception handler
    740     add esp,4       // EAX = ContextRecord
    741     mov ebx,eax   // dr0=>ebx
    742     mov eax,dword ptr [esp+$c]      // set ContextRecord.EIP
    743     inc dword ptr [eax+$b8]
    744     mov dword ptr [eax+$b0],ebx   // dr0=>eax
    745     xor eax,eax
    746     ret
    747 
    748   @e_handler1:         // EAX = ContextRecord
    749     mov eax,dword ptr [esp+$c]      // set ContextRecord.EIP
    750     inc dword ptr [eax+$b8]
    751     mov ebx,dword ptr[eax+$04]
    752     mov dword ptr [eax+$b0],ebx   // dr0=>eax
    753     xor eax,eax
    754     ret
    755 
    756   @IsDebug:
    757     mov @result, 1
    758     mov esp,ebp
    759     pop ebp
    760     ret
    761   @Exit:
    762     mov esp,ebp
    763     pop ebp
    764     ret
    765   end;
    766 end;
    767 
    768 // 使用int1的异常检测来反调试
    769 function FS_SI_Exception_Int1(): Boolean;
    770 begin
    771   asm
    772     mov @result, 0
    773     push offset @eh_int1 // set exception handler
    774     push dword ptr fs:[0h]
    775     mov dword ptr fs:[0h],esp
    776     xor eax,eax   // reset flag(EAX) invoke int3
    777     int 1h
    778     pop dword ptr fs:[0h] // restore exception handler
    779     add esp,4
    780     test eax, eax   // check the flag
    781     je @IsDebug
    782     jmp @Exit
    783 
    784   @eh_int1:
    785     mov eax,[esp+$4]
    786     mov ebx,dword ptr [eax]
    787     mov eax,dword ptr [esp+$c] // EAX = ContextRecord
    788     mov dword ptr [eax+$b0],1 // set flag (ContextRecord.EAX)
    789     inc dword ptr [eax+$b8] // set ContextRecord.EIP
    790     inc dword ptr [eax+$b8] // set ContextRecord.EIP
    791     xor eax, eax
    792     ret
    793   @IsDebug:
    794     mov @result, 1
    795     mov esp,ebp
    796     pop ebp
    797     ret
    798   @Exit:
    799     xor eax, eax
    800     mov esp,ebp
    801     pop ebp
    802     ret
    803   end;
    804 end;
    805 
    806 function IsInsideVMWare(): Boolean;
    807 var
    808   r: Boolean;
    809 begin
    810   asm
    811     push edx
    812     push ecx
    813     push ebx
    814 
    815     mov eax,'VMXh'
    816     mov ebx,0     // any value but MAGIC VALUE
    817     mov ecx,10    // get VMWare version
    818     mov edx,'VX'  // port number
    819     in eax,dx     // read port
    820     // on return EAX returns the VERSION
    821     cmp ebx,'VMXh'// is it a reply from VMWare?
    822     setz [r]      // set return value
    823 
    824     pop ebx
    825     pop ecx
    826     pop edx
    827   end;
    828   Result := r;
    829 end;
    830 
    831 function FV_VMWare_VMX(): Boolean;
    832 begin
    833   try
    834     Result := IsInsideVMWare;
    835   except
    836     Result := false;
    837   end;
    838 end;
    839 
    840 function IsRunInVPC(out ErrMsg: string): Boolean;
    841 begin
    842   Result := false;
    843   try
    844     asm
    845       push ebx
    846       mov ebx, 0
    847       mov eax, 1
    848       db 0Fh, 3Fh, 07h, 0Bh
    849       test ebx, ebx
    850       setz [Result]
    851       pop ebx
    852     end;
    853   except
    854     on e: Exception do
    855       ErrMsg := e.Message;
    856   end;
    857 end;
    858 
    859 function FV_VPC_Exception(): Boolean;
    860 begin
    861   asm
    862     push ebp
    863     mov ebp,esp
    864 
    865     mov ecx,offset @exception_handler
    866 
    867     push ebx
    868     push ecx
    869 
    870     push dword ptr fs:[0]
    871     mov dword ptr fs:[0],esp
    872 
    873     mov ebx,0  // flag
    874     mov eax,1  // VPC function number
    875 
    876     // _asm __emit 0Fh
    877     // _asm __emit 3Fh
    878     // _asm __emit 07h
    879     // _asm __emit 0Bh
    880     db 0Fh, 3Fh, 07h, 0Bh
    881 
    882     mov eax,dword ptr ss:[esp]
    883     mov dword ptr fs:[0],eax
    884 
    885     add esp,8
    886     test ebx,ebx
    887 
    888     setz al
    889 
    890     lea esp,dword ptr ss:[ebp-4]
    891     mov ebx,dword ptr ss:[esp]
    892     mov ebp,dword ptr ss:[esp + 4]
    893 
    894     add esp,8
    895     jmp @ret1
    896   @exception_handler:
    897     mov ecx,[esp + 0Ch]
    898     mov dword ptr [ecx + 0A4h],-1
    899     add dword ptr [ecx + 0B8h],4
    900     xor eax,eax
    901     ret
    902     mov @result,1  // ret
    903   @ret1:
    904     mov @result,0  // ret
    905     ret
    906   end;
    907 end;
    908 
    909 // 在异常处理过程中检测硬件断点
    910 function FB_HWBP_Exception(): Boolean;
    911 begin
    912   asm
    913     push offset @exeception_handler // set exception handler
    914     push dword ptr fs:[0h]
    915     mov dword ptr fs:[0h],esp
    916     xor eax,eax   // reset EAX invoke int3
    917     int 1h
    918     pop dword ptr fs:[0h]   // restore exception handler
    919     add esp,4   // test if EAX was updated (breakpoint identified)
    920     test eax,eax
    921     jnz @IsDebug
    922     jmp @Exit
    923 
    924   @exeception_handler:        // EAX = CONTEXT record
    925     mov eax,dword ptr [esp+$c]   // check if Debug Registers Context.Dr0-Dr3 is not zero
    926     cmp dword ptr [eax+$04],0
    927     jne @hardware_bp_found
    928     cmp dword ptr [eax+$08],0
    929     jne @hardware_bp_found
    930     cmp dword ptr [eax+$0c],0
    931     jne @hardware_bp_found
    932     cmp dword ptr [eax+$10],0
    933     jne @hardware_bp_found
    934     jmp @exception_ret
    935   @hardware_bp_found: // set Context.EAX to signal breakpoint found
    936     mov dword ptr [eax+$b0],$FFFFFFFF
    937   @exception_ret:        // set Context.EIP upon return
    938     inc dword ptr [eax+$b8] // set ContextRecord.EIP
    939     inc dword ptr [eax+$b8] // set ContextRecord.EIP
    940     xor eax,eax
    941     ret
    942   @IsDebug:
    943     mov @result, 1
    944     mov esp,ebp
    945     pop ebp
    946     ret
    947   @Exit:
    948     xor eax, eax
    949     mov esp,ebp
    950     pop ebp
    951     ret
    952   end;
    953 end;
    954 
    955 end.

    //代码大部分来自网络

  • 相关阅读:
    开课吧-孤尽公开课视频内容整理笔记
    业务系统数据库设计经验总结(七)-强制使用选定索引
    业务系统数据库设计经验总结(六)-MySQL中ORDER BY LIMIT分页数据性能问题
    业务系统数据库设计经验总结(五)-MySQL中ORDER BY LIMIT分页数据重复问题
    mongoTemplate聚合统计字段类型为字符串的数据,根据时间日期月份进行统计,日期也为字符串
    预览在线的pdf
    react页面缓存 使用本地存储
    react页面缓存插件 react-router-cache-router
    README.md的基本语法使用
    eclipse tomcat的一些错误
  • 原文地址:https://www.cnblogs.com/xspace/p/2882443.html
Copyright © 2011-2022 走看看