Hide user mode debuggers from executables with debbuger detection
By: j0epub
原文出处:
http://www.rootkit.com/newsread.php?newsid=284
There are various techniques that copy protection schemes can use to detect whether their
applications are being debugged. What I inted to do is to prevent these types of
applications from detecting a user mode debbuger using the top two common methods. Please
note that the method used for detecting user mode debuggers do not apply to kernel mode
debuggers like SoftIce. There are other methods used to detect debuggers like SoftIce but I
will not cover those in this article.
Some of the methods used
Calling the kernel32 function IsDebuggerPresent
Checking a flag within the PEB (via fs:30h or fs:18h)
NtQueryInformationProcess with a class type of ProcessDebugPort
All the above methods are used by a commonly known commercial CD copy protection scheme
(cough cough), and by implementing the hooks the software no longer detected the attached
debugger (WinDbg, IDA and VS.NET tested)
The IsDebbugerPresent call basicly uses the fs:18h method to get a pointer the the TIB and
then from there retrevies a pointer to the PEB to retreive the relevant flag. So we will
eliminate the API IsDebuggerPresent call via solving the second method.
PEB (Process Enviroment Block) is a structure that all processes have present which contain
information related to that particualr process.
Here is the top of the undocumented PEB structure, notice the BeingDebugged member which is
if(NT_SUCCESS(status))
{
//check to see if an application is querying wether it's debug port is set
//and do some sanity checks also just in case
if(ProcessInformationClass == ProcessDebugPort && ProcessInformation != NULL &&
I had a few other ideas for debugger detection... I have no idea if anyone uses these, but you might want to consider them:
1) CSRSS and/or SMSS may keep some information on who is debugging and who is being debugged... Maybe it's possible to find this information using ReadProcessMemory, or maybe you can just ask them over LPC? (for a place to start, you can load SMSS.EXE with symbols and search for "HashTable")
2) If a process is created in a debugger, and it's allowed to initialize before you clear the "being debugged" flag, LdrpInitialize will create the process heap with certain flags, I think HEAP_TAIL_CHECKING_ENABLED and HEAP_FREE_CHECKING_ENABLED but I'm not sure. This could be a giveaway, but it's a theoretically-poor technique because possibly other factors (NtGlobalFlag?) could set these heap flags as well.
3) Here's the best one: a process can raise a 40010006h (DBG_PRINTEXCEPTION_C) exception, and if it's being debugged, this exception will be swallowed by WaitForDebugEvent (it's what OutputDebugString and DbgPrint use to send debug output) and regurgitated as an OUTPUT_DEBUG_STRING_EVENT instead of an EXCEPTION_DEBUG_EVENT. If it's not being debugged, then the thread's KiUserExceptionDispatcher will be called as normal. A very crafty debugger could do all the LPC itself and actually see the 0x40010006 exception, but a normal debugger using WaitForDebugEvent doesn't get a choice.
It appears that RaiseException(0x80000003) (STATUS_BREAKPOINT) may get special treatment by NTOSKRNL, and 0x80000003 and 0x80000004 (STATUS_SINGLE_STEP) may be recognized specially by SMSS, which passes it to the debugger. These might be worth exploring further, since special processing in NTOSKRNL, CSRSS, or SMSS could preclude the debugger from any chance of receiving the original message, a discrepancy that could be exploited as an anti-debugging trick.
Sorry for the lack of hard facts, this is just a kinda cursory brainstorm on anti-debugging tricks.