zoukankan      html  css  js  c++  java
  • 游戏是如何检测到有OD等调试工具的

    知其然,知其所以然,希望大家觉得有用,大家可以用在自己程序中查看自己的程序是否被调试..同时为了更好的了解一些游戏无法用OD调试的原因


    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';
    var
      hSnap,hProcess:THandle;
      szBuffer:array[0..MAX_PATH] of char;
      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);
      //查找进程
      LoopFlag:=Process32First(hSnap,Process32);
      if LoopFlag=False then
      begin
        CloseHandle(hSnap);
        Result:=False;
        Exit;
      end;
      while Integer(LoopFlag)<>0 do
        begin
          if Process32.th32ProcessID=GetCurrentProcessId() then
            begin
              hProcess:=OpenProcess(PROCESS_ALL_ACCESS,FALSE,Process32.th32ParentProcessID);
              if hProcess<>0 then
                begin
                  if GetModuleFileNameEx(hProcess,0,FileName,MAX_PATH)<>0 then
                    begin
                      //取得系统目录
                      GetWindowsDirectory(szBuffer,MAX_PATH);
                      //合并系统目录和\EXPLORER.EXE
                      StrCat(szBuffer,ParentName);
                      //转换成大写以后比较当前调试程序的进程是否为父进程
                      if UpperCase(String(FileName))<>UpperCase(String(szBuffer)) then
                        Result:=True
                      else
                        Result:=False;
                    end;
                end
              else
                Result:=False;
            end;
          LoopFlag:=Process32Next(hSnap,Process32);
        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;

     

    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;

  • 相关阅读:
    维控PLC与电流变送器modbus通讯获取电流变送器数据
    openmv第一次调试
    电流变送器(互感器)
    物联网数据采集
    STM32编程环境配置(kile5)
    开发日记9
    开发日记8
    开发日记7
    开发日记6
    开发日记5
  • 原文地址:https://www.cnblogs.com/huhu0013/p/2000716.html
Copyright © 2011-2022 走看看