// Use the API: CheckRemoteDebuggerPresent
function FD_CheckRemoteDebuggerPresent(): Boolean;
var
Func_Addr: Pointer;
hModule: Cardinal;
pDebugBool: PBool;
begin
result := false;
hModule := GetModuleHandle('
kernel32.dll');
if hModule = INVALID_HANDLE_VALUE
then exit;
Func_addr := GetProcAddress(hModule, '
CheckRemoteDebuggerPresent');
if (Func_addr <>
nil)
then begin
asm
lea eax, pDebugBool
push eax
push $ffffffff
call Func_addr
cmp dword ptr[pDebugBool], 0
jne @IsDebug
jmp @exit
@IsDebug:
mov @result, 1
@exit:
end;
end;
end;
// Use ntdll_NtQueryInformationProcess () to query
// ProcessDebugPort can be used to detect anti-debugging
function FD_NtQueryInfoProc_DbgPort(): Boolean;
var
Func_Addr: Pointer;
hModule: Cardinal;
ReturnLength: PULONG;
dwDebugPort: PDWORD;
begin
result := false;
hModule := GetModuleHandle('
ntdll.dll');
if hModule = INVALID_HANDLE_VALUE
then exit;
Func_addr := GetProcAddress(hModule, '
ZwQueryInformationProcess');
if (Func_addr <>
nil)
then begin
asm
lea eax, ReturnLength
push eax
//ReturnLength
push 4
//ProcessInformationLength
lea eax, dwDebugPort
push eax
//ProcessInformation
push 7
//ProcessInformationClass
push $FFFFFFFF
//ProcessHandle
call Func_addr
//NtQueryInformationProcess
cmp [dwDebugPort], 0
jne @IsDebug
jmp @exit
@IsDebug:
mov @result, 1
@exit:
end;
end;
end;
// Check winXp automatically create the "debug object",
// Not open ProcessDebugFlags class, when the debugger is present, it will return false
function FD_NtQueryInfoProc_DbgFlags(): Boolean;
var
Func_Addr: Pointer;
hModule: Cardinal;
ReturnLength: PULONG;
dwDebugPort: PDWORD;
begin
result := false;
hModule := GetModuleHandle('
ntdll.dll');
if hModule = INVALID_HANDLE_VALUE
then exit;
Func_addr := GetProcAddress(hModule, '
ZwQueryInformationProcess');
if (Func_addr <>
nil)
then begin
asm
lea eax, ReturnLength
push eax
push 4
lea eax, dwDebugPort
push eax
push $1F
push $FFFFFFFF
call Func_addr
mov eax, [dwDebugPort]
test eax, eax
jz @IsDebug
jmp @exit
@IsDebug:
mov @result, 1
@exit:
end;
end;
end;
// Int3 Detection
function FD_Exception_Int3(): Boolean;
begin
asm
mov @result, 0
push offset @exception_handler
//set exception handler
push dword ptr fs:[0h]
mov dword ptr fs:[0h],esp
xor eax,eax
//reset EAX invoke int3
int 3h
pop dword ptr fs:[0h]
//restore exception handler
add esp,4
test eax,eax
// check the flag
je @IsDebug
jmp @exit
@exception_handler:
mov eax,dword ptr [esp+$c]
//EAX = ContextRecord
mov dword ptr [eax+$b0],$ffffffff
//set flag (ContextRecord.EAX)
inc dword ptr [eax+$b8]
//set ContextRecord.EIP
xor eax,eax
ret
@IsDebug:
xor eax,eax
inc eax
mov esp,ebp
pop ebp
ret
@exit:
xor eax,eax
mov esp,ebp
pop ebp
ret
end;
end;
// Use int 2dh anomaly detection interrupt
function FD_INT_2d(): Boolean;
begin
try
asm
int 2dh
inc eax
//any opcode of singlebyte.
//;or u can put some junkcode,
//"0xc8"..."0xc2"..."0xe8"..."0xe9"
mov @result, 1
end;
except
Result := false;
end;
end;