Delphi反调试【初级】检测法

2022-12-14 12:42:05 作者:admin

本文整理自网络,侵删。

 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判断系统是否安装tcp/ip协议

Delphi 获取闪盘列表

Delphi 使用资源文件

Delphi 时间与相关类型(3): tfiletime、tsystemtime 及 dos 时间

Delphi xe2-firemonkey 新功能

Delphi debug release区别是什么?

Delphi下载程序并且urldownloadtofile的进度提示

Delphi编程之桌面图标设置

Delphi xe 提权代码

Delphi cxgrid使用小结

更多相关阅读请进入《Delphi》频道 >>



在线咨询 拨打电话