.data?
hProcess HANDLE ?
hDebuggerProcess HANDLE ?
ReturnLength DWORD ?
pCLIENT_ID CLIENT_ID <>
pEventObject_ATTRIBUTES OBJECT_ATTRIBUTES <>
pPROCESS_BASIC_INFORMATION PROCESS_BASIC_INFORMATION <>
.code
lea edi, pEventObject_ATTRIBUTES
lea esi, pCLIENT_ID
assume edi

tr OBJECT_ATTRIBUTES
mov [edi].dwLength, sizeof OBJECT_ATTRIBUTES
mov [edi].RootDirectory, 0
mov [edi].ObjectName, 0
; can set to object name if ClientID.UniqueProcess not used
mov [edi].Attributes, 0
mov [edi].SecurityDescriptor, 0
mov [edi].SecurityQualityOfService, 0
assume esi

tr CLIENT_ID
invoke PsGetCurrentProcessId ; check if our own app is being debugged
mov [esi].UniqueProcess, eax
mov [esi].UniqueThread, 0
invoke ZwOpenProcess, offset hProcess,\ ; OUT PHANDLE phProcess
PROCESS_ALL_ACCESS,\ ; IN ACCESS_MASK AccessMask
edi,\ ; IN pEventObject_ATTRIBUTES ObjectAttributes
esi ; IN PCLIENT_ID pClientId
invoke ZwQueryInformationProcess, hProcess,\
ProcessBasicInformation,\ ; ntddk.inc ; enum _PROCESSINFOCLASS
offset pPROCESS_BASIC_INFORMATION,\
SIZEOF pPROCESS_BASIC_INFORMATION,\
offset ReturnLength
; invoke ZwClose, hProcess ; can delete now useless thread handle
;--------------------------------------------------------
mov eax, pPROCESS_BASIC_INFORMATION.PebBaseAddress
bt dword ptr [eax], 16
; Bit Test to see if BeingDebugged flag is at byte 002 of PEB
jc @F
jmp nodebugger
@@:
;===================================================
; Let's get the handle of the debugger so we can kill it:
mov eax, pPROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessId ; Debugger PID
; redefine CLIENT_ID to that of the remote process
mov [esi].UniqueProcess, eax
invoke ZwOpenProcess, offset hDebuggerProcess,\ ; OUT PHANDLE phProcess
PROCESS_ALL_ACCESS,\ ; IN ACCESS_MASK AccessMask
edi,\ ; IN pEventObject_ATTRIBUTES ObjectAttributes
esi ; IN PCLIENT_ID pClientId
; Debugger handle is now in hDebuggerProcess,
; exit driver, clean up and kill the process
;...
nodebugger:
assume esi:nothing
assume edi:nothing