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

Delphi 19种反调试检测法的更多相关文章

  1. 编译Android内核 For nexus 5 以及绕过Android的反调试

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/54880488 前面的博客中已经记录了Nexus 5手机的Android 4.4.4 ...

  2. Windows 32位-调试与反调试

    1.加载调试符号链接文件并放入d:/symbols目录下. 0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/s ...

  3. C/C++ 程序反调试的方法

    C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...

  4. 一种绕过PTRACE反调试的办法

    Linux 系统gdb等调试器,都是通过ptrace系统调用实现.Android加固中,ptrace自身防止调试器附加是一种常用的反调试手段. 调试时一般需要手工在ptrace处下断点,通过修改ptr ...

  5. JavaScript反调试技巧

    一.函数重定义 这是一种最基本也是最常用的代码反调试技术了.在JavaScript中,我们可以对用于收集信息的函数进行重定义.比如说,console.log()函数可以用来收集函数和变量等信息,并将其 ...

  6. WIN10 X64下通过TLS实现反调试

    目录(?)[-] TLS技术简介 1 TLS回调函数 2 TLS的数据结构 具体实现及原理 1 VS2015 X64 release下的demo 2 回调函数的具体实现 21 使用IsDebugger ...

  7. Windows 反调试技术——OpenProcess 权限过滤 - ObRegisterCallback

    转载: https://blog.xpnsec.com/anti-debug-openprocess/ 看雪翻译:https://bbs.pediy.com/thread-223857.htm 本周我 ...

  8. 解决Android加固多进程ptrace反调试的思路整理

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/53613481 一.Android多进程反调试的原理代码 当ptrace附加目标进程 ...

  9. 基于TLS的反调试技术

    TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...

随机推荐

  1. [转]使用 mitmproxy + python 做拦截代理

    使用 mitmproxy + python 做拦截代理   本文是一个较为完整的 mitmproxy 教程,侧重于介绍如何开发拦截脚本,帮助读者能够快速得到一个自定义的代理工具. 本文假设读者有基本的 ...

  2. .NET C#错误:所生成项目的处理器框架“MSIL”与引用“wdapi_dotnet1021”的处理器架构“AMD64”不匹配

    .NET C#错误:所生成项目的处理器框架“MSIL”与引用“wdapi_dotnet1021”的处理器架构“AMD64”不匹配. 直接在项目右键属性->生成->x64. 即可解决

  3. 破解验证码模拟登陆cnblogs

    from selenium import webdriver from selenium.webdriver import ActionChains from PIL import Image imp ...

  4. 设置文字小于12px

    问题:有时候会需要设置一些小于12px的字或是icon: 方法:使用css3的transform的scale,来放大和缩小,但是相应的容器也会缩小 transform: scale(0.6);

  5. Pandas DataFrame数据的增、删、改、查

    Pandas DataFrame数据的增.删.改.查 https://blog.csdn.net/zhangchuang601/article/details/79583551 #删除列 df_2 = ...

  6. 解决C/C++语言中全局变量重复定义的问题

    前言 今天,在整理自己的代码的时候,考虑到我写的代码从一至终都是在一个cpp文件里面.于是,想把自己的代码中的各个模块分离开来,以便更好地阅读和管理. 遇到的问题 我的做法是: 宏定义.结构体定义.函 ...

  7. 发布构件到Maven中央仓库

    一.注册jira账号 访问如下网址: https://issues.sonatype.org/secure/Signup.jspa 记住邮箱,用户名,密码以备以后使用,一定牢记. 二.创建一个issu ...

  8. conda管理python包

    参考:http://blog.sina.com.cn/s/blog_c3c116470102wlv5.html 查看python,numpy,scipy,matplotlib的版本及安装位置: htt ...

  9. Lambda表达式浅析

    Lambda 表达式是一种可用于创建"委托"或"表达式目录树"类型的"匿名函数".通过使用 lambda 表达式,可以写入可作为参数传递或作 ...

  10. 【LOJ】#2549. 「JSOI2018」战争

    题解 仔细分析了一下,如果写个凸包+每次暴力半平面交可以得到70分,正解有点懵啊 然后用到了一个非常结论,但是大概出题人觉得江苏神仙一个个都可以手证的结论吧.. Minkowski sum 两个凸包分 ...