Delphi反调试【初级】检测法

2016-08-22 10:19:07来源:http://science.blog.51cto.com/1396632/288185作者:sunnyzjj人点击


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;







最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台