Delphi反调试【初级】检测法

1.程序窗口句柄检测

原理:用FindWindow函数查找具有相同窗口类名和标题的窗口,如果找到就说明有OD在运行

//********************************************

//通过查找窗口类名来实现检测OllyDBG

//********************************************

function AntiLoader():Boolean;

const

OllyName='OLLYDBG';

var

Hwnd:Thandle;

begin

Hwnd:=FindWindow(OllyName,nil);

if Hwnd<>0 then

    Result:=True

else

    Result:=False;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

if AntiLoader then

    MessageBox(Handle,'找到调试器!','提示',MB_OK+MB_ICONINFORMATION)

else

    MessageBox(Handle,'未找到调试器!','提示',MB_OK+MB_ICONINFORMATION)

end;

 

2.用线程环境块检测

原理:用ring3级下的调试器对可执行程序进行调试时,调试器会把被调试的可执行程序作为一个子线程进行跟踪.这时被调试的可执行程序的PEB结构偏移0x02处的BeingDebugged的值为1,如果可执行程序未被调试,则值为0,所以可以利用这个值来检测程序是否被ring3级下的调试器调试

//***************************************

//使用PEB结构检测OllyDBG

//***************************************

function AntiLoader():Boolean; //检测调试器;

var

YInt,NInt:Integer;

begin

asm

    mov eax,fs:[$30]

    //获取PEB偏移2h处BeingDebugged的值

    movzx eax,byte ptr[eax+$2]

    or al,al

    jz @No

    jnz @Yes

    @No:

      mov NInt,1

    @Yes:

      Mov YInt,1

end;

if YInt=1 then

    Result:=True;

if NInt=1 then

    Result:=False;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

if AntiLoader then

    MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)

else

    MessageBox(Handle,'未发现调试器!','提示',MB_OK+MB_ICONINFORMATION);

end;

 

3.用API函数IsDebuggerPresent检测

原理:操作系统将调试对象设置为在特殊环境中运行,而kernel32.dll中的API函数IsDebuggerPresent的功能是用于判断进程是否处于调试环境中,这样就可以利用这个API函数来查看进程是否在调试器中执行

//****************************************

//利用IsDebuggerPresent函数检测OllyDBG

//****************************************

function AntiLoader():Boolean;

var

isDebuggerPresent: function:Boolean;

Addr: THandle;

begin

Addr := LoadLibrary('kernel32.dll');

isDebuggerPresent := GetProcAddress(Addr, 'IsDebuggerPresent');

if isDebuggerPresent then

    Result:=True

else

    Result:=False;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

if AntiLoader then

    MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)

else

    MessageBox(Handle,'未发现提示器!','提示',MB_OK+MB_ICONINFORMATION);

end;

 

4.检查程序的父进程

原理:Windows操作系统下的GUI可执行程序的父进程都是explorer.exe(CUI可执行程序的父进程是CMD.exe,系统服务的父进程是Service.exe,在实际使用的时候需要根据自己的程序类型来选择父进程实现反跟踪),而正被调试器OD调试的程序的父进程是调试器的执行程序ollydbg.exe而不是别的.所以可以利用检查父进程是否为explorer.exe的方法来检测OD.

//***************************************************

//检查父进程来检测OllyDBG

//***************************************************

方法一:

function AntiLoader(): Boolean;

const

  ParentName = '\EXPLORER.EXE';

  //GUI可执行程序的父进程都是explorer.exe,CUI可执行程序的父进程是CMD.exe,系统服务的父进程是Service.exe

var

  hSnap, hProcess: THandle;

  //HANDLE(句柄)指的是一个核心对象在某一个进程中的唯一索引, HWND是其中一种,HWND是HANDLE,但HANDLE不只是HWND

  szBuffer: array[0..MAX_PATH] of Char;  //Buffer:缓冲的意思

  FileName: array[0..MAX_PATH] of Char;

  Process32: PROCESSENTRY32; //存放进程信息和调用成员输出进程信息

  LoopFlag: BOOL;

begin

  hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

  //得到所有进程的列表快照

  if hSnap = INVALID_HANDLE_VALUE then  //如果获取进程快照失败

  begin

    Result := false;

    Exit;

  end;

  Process32.dwSize := SizeOf(PROCESSENTRY32);

  //sizeof(PROCESSENTRY32)指的是设置成员的大小,如果不设置Process32First调用会失败

  //查找进程

  LoopFlag := Process32First(hSnap, Process32);

  //Process32First:指向第一个进程信息,并将进程信息抽取到PROCESSENTRY32中

  if LoopFlag = false then

  begin

    CloseHandle(hSnap);

    Result := false;

    Exit;

  end;

  while Integer(LoopFlag) <> 0 do

  begin

    if Process32.th32ProcessID = GetCurrentProcessId() then

    //th32ProcessID:进程的ID, GetCurrentProcessId:此刻CPU正在执行的进程的ID

    begin

      hProcess := OpenProcess(PROCESS_ALL_ACCESS, false,

        Process32.th32ParentProcessID);

      // OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄, 如成功,返回值为指定进程的句柄,零表示失败,th32ParentProcessID:父进程的ID

      if hProcess <> 0 then  //如果打开进程并返回句柄成功

      begin

        if GetModuleFileNameEx(hProcess, 0, FileName, MAX_PATH) <> 0 then

        // GetModuleFileNameEx指的是获得指定进程的全路径, 如果你的32位应用程序是运行在Windows XP或者以上的操作系统上的,推荐的解决方案是使用GetProccessImageFileName来替代GetModuleFileNameEx来取得进程的全路径

        begin

          GetWindowsDirectory(szBuffer, MAX_PATH); //取得系统目录

          StrCat(szBuffer, ParentName); //合并系统目录和\EXPLORER.EXE。StrCat():将第二个字符串添加到第一个字符串的结尾,从而使第一个字符串成为一个新的组合字符串,第二个字符串不改变

          if UpperCase(string(FileName)) <> UpperCase(string(szBuffer)) then

          //转换成大写以后比较当前调试本程序的进程是否为父进程(explorer.exe),如果不是父进程

          begin

            Result := true;

            TerminateProcess(hProcess, 0);//杀之而后快,哈哈

          end

          else

          begin

            Result := false;

          end;

        end;

      end

      else

        Result := false;

    end;

    LoopFlag := Process32Next(hSnap, Process32);

    //Process32Next:指向下一条进程信息

  end;

  CloseHandle(hSnap);

end;

 

procedure TForm1.FormCreate(Sender: TObject);

 

 

 

begin

if AntiLoader then

    MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)

else

    MessageBox(Handle,'未发现调试器!','提示',MB_OK+MB_ICONINFORMATION)

end;

 

方法二:

 

 

procedure CheckParentProc;
var //检查自己的进程的父进程
  Pn: TProcesseNtry32;
  sHandle:THandle;
  H,ExplProc,ParentProc:Hwnd;
  Found:Boolean;
  Buffer:array[0..1023]of Char;
  Path:string;

begin
  H:= 0;
  ExplProc:= 0;
  ParentProc:= 0;
  //得到Windows的目录
  SetString(Path,Buffer)
  GetWindowsDirectory(Buffer,Sizeof(Buffer)- 1));
  Path:= UpperCase(Path)+ '\EX PLORER.EXE';//得到Explorer的路径
  //得到所有进程的列表快照
  sHandle:= CreateToolHelp32Snap Shot(TH32CS_SNAPALL,0);
  Found:= Process32First(sHandle,Pn);//查找进程
  while Found do //遍历所有进程
  begin
  if Pn.szExeFile = ParamStr(0)then //自己的进程
  begin
  ParentProc:= Pn.th32ParentProcessID://得到父进程的进程ID
  //父进程的句柄
  H:= OpenProcess(PRO CESS_ALL_ACCESS,True,Pn.th32Parent ProcessID);
  end
  else if UpperCase(Pn.szExeFile)= Path then
  ExplProc:= Pn.th32ProcessID;//Ex plorer的PID
  Found:= Process32Next(sHandle,Pn);//查找下一个
  end;
  //父进程不是Explorer,是调试器……
  if ParentProc <> ExplProc then
  begin
  TerminateProcess(H,0);//杀之!除之而后快也! :)
  //你还可以加上其它什么死机代码来消遣消遣这位可爱的Cracker:)
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);

begin

CheckParentProc;

End;

 

5.检查STARTUPINFO结构

原理:Windows操作系统中的explorer.exe创建进程的时候会把STARTUPINFO结构中的值设为0,而非explorer.exe创建进程的时候会忽略这个结构中的值,也就是结构中的值不为0,所以可以利用这个来判断OD是否在调试程序.

/************************************************

//通过检测STARTUPINFO结构来检测OllyDbg

//************************************************

function AntiLoader():Boolean;

var

Info:STARTUPINFO;

begin

GetStartupInfo(Info);

if (Info.dwX<>0) or (Info.dwY<>0) or (Info.dwXCountChars<>0) or (Info.dwYCountChars<>0) or

     (Info.dwFillAttribute<>0) or (Info.dwXSize<>0) or (Info.dwYSize<>0) then

    Result:=True

else

    Result:=False;

end;

procedure TMainFrm.FormCreate(Sender: TObject);

begin

if AntiLoader then

    MessageBox(Handle,'发现调试器!','提示',MB_OK)

else

    MessageBox(Handle,'未发现调试器!','提示',MB_OK);

end;

 


你可能感兴趣的:(Delphi反调试【初级】检测法)