Created
April 8, 2012 14:23
-
-
Save melice/2337560 to your computer and use it in GitHub Desktop.
反调试技术(以OD为例附核心原代码)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
反调试技术(以OD为例附核心原代码) | |
【标 题】:反调试技术(以OD为例附核心原代码) | |
【作 者】:★天&緣★ | |
【时 间】:2007-11-16 18:14 | |
【链 接】:http://www.wgum.net/viewthread.php?tid=980 | |
知其然,知其所以然,希望大家觉得有用,大家可以用在自己程序中查看自己的程序是否被调试..同时为了更好的了解一些游戏无法用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; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment