2.1.4 CloseHandle
As with an invalid
handle, if a protected
handle is passed
to the kernel32 CloseHandle() function (or directly to
the ntdll NtClose() function) and no debugger is present,
then an error code is returned. However, if a debugger is
present, an EXCEPTION_HANDLE_NOT_CLOSABLE
(0xC0000235)
exception will be raised. This
exception can
be intercepted by an
exception handler, and is an indication
that a debugger is running.
Example code looks like this:
xor eax, eax
push offset being_debugged
push d fs:[eax]
mov fs:[eax], esp
push eax
push eax
push 3 ;OPEN_EXISTING
push eax
push eax
push 80000000h ;GENERIC_READ
push offset l1
call CreateFileA
push eax
;HANDLE_FLAG_PROTECT_FROM_CLOSE
push 2
push -1
xchg ebx, eax
call SetHandleInformation
push ebx
call CloseHandle
...
l1:
db “myfile”, 0
Defeating this method is easiest on Windows XP, where a
FirstHandler Vectored
Exception Handler can be registered
by the debugger to hide the
exception and silently resume
execution. Of course, there is the problem of hooking
the kernel32 AddVectoredExceptionHandler() function
transparently, in order to prevent another handler from
registering as the fi rst handler. However, it is still easier
than the transparently hooking the ntdll NtClose() function
on Windows NT and Windows 2000 in order to register a
Structured
Exception Handler to hide the
exception. This
method has been disclosed publicly [4].