这段代码的Anti-Debug原理其实非常简单,也是目前非常普遍的一种检测DeBUGGER的方法,它利用WINDOWS的API函数CreateFileA来试图打开调试器的驱动程序句柄,这就是著名的“MeltICE”方法,制作出SoftICE和SmartCheck的NuMega公司的程序员就是利用这个方法来使Symbol Loader检查softice是否已经激活 (这段代码位于nmtrans.dll中),虽然这个方法最初来源于softice,但是它对其它类型的debugger检测依然有效,而且实现方法简单易行,以至于后来越来越多的软件都是用这种方法检测DeBUGGer的存在,比如美萍系列软件,著名的幻影(DBPE),Acrobat Reader等等。
以下是一些调试器的驱动程序句柄有:
SICE, SIWVID (对应softice Win9x版) NTICE (对应softice WinNT版) TRW、TRW2000、TRDEBUG (对应TRWIN) REGVXD (对应Registry Monitor) BW2K (DBoy的冲击波2000) FILEVXD (对应File Monitor) …… ……
根据这些我们来补全这个Anti-DeBUGGer源代码: —————————————————————————————————————————— unit StopIce;
interface
implementation
uses Windows;
Function IsSoftIce95Loaded: boolean; //声明一个检测SoftICE的boolean型变量 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\SICE’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsSoftIceNTLoaded: boolean; //声明一个检测SoftIceNT的boolean型变量 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\NTICE’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsTRWLoaded: boolean; //声明一个检测TRW的boolean型变量 可以对付我修改过的那个TRW2000 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\TRWDEBUG’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsTRW2000Loaded: boolean; //声明一个检测TRW2000的boolean型变量 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\TRW2000’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsRegMONLoaded: boolean; //声明一个检测RegMON的boolean型变量 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\REGVXD’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsFileMONLoaded: boolean; //声明一个检测FileMON的boolean型变量 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\FILEVXD’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
Function IsBW2000Loaded: boolean; //声明一个检测冲击波2000的boolean型变量 加壳时说不定用的上 Var hFile: Thandle; Begin result := false; hFile := CreateFileA(’\\.\bw2k’, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFile <> INVALID_HANDLE_VALUE ) then begin CloseHandle(hFile); result := TRUE; end; End;
function WinExit(flags: integer): boolean; function SetPrivilege(privilegeName: string; enable: boolean): boolean; var tpPrev, tp : TTokenPrivileges; token : THandle; dwRetLen : DWord; begin result := False; OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token); tp.PrivilegeCount := 1; if LookupPrivilegeValue(nil, pchar(privilegeName), tp.Privileges[0].LUID) then begin if enable then tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED else tp.Privileges[0].Attributes := 0; dwRetLen := 0; result := AdjustTokenPrivileges(token, False, tp, SizeOf(tpPrev), tpPrev, dwRetLen); end; CloseHandle(token); end; begin if SetPrivilege(’SeShutdownPrivilege’, true) then begin ExitWindowsEx(flags, 0); SetPrivilege(’SeShutdownPrivilege’, False) end; end;
initialization if IsSoftIce95Loaded or IsSoftIceNTLoaded or IsBW2000Loaded or IsFileMONLoaded or IsRegMONLoaded IsTRW2000Loaded or IsTRWLoaded then begin //若上述声明的任何一个函数值为True则关机 WinExit(EWX_SHUTDOWN or EWX_FORCE); Halt; end; end.
——————————————————————————————————————————————
但如果你直接用CREATEFILEA来设断拦截是没用的 为了检测这些检测程序,我们可以在softice中通过下面的断点来拦截它们: BPX CreateFileA if *(esp->4+4)==’SICE’ || *(esp->4+4)==’SIWV’ || *(esp->4+4)==’NTIC’ BPINT 30 if eax==002A001F && (*edi==’SICE’ || *edi==’SIWV’) ; 将会中断3次 BPINT 30 if (*edi==’SICE’ || *edi==’SIWV’) BPX KERNEL32!ORD_0001 if *edi==’SICE’ || *edi==’SIWV’ ; 将会中断3次 BPX VMM_GetDDBList if eax->3==’SICE’ || eax->3==’SIWV’ BPX CreateFileA if *(esp->4+4)==’TRW’ (这个可以断美萍)
|