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
what we will be concentrating on
typedef struct _PEB
{
BOOL InheritedAddressSpace;
BOOL ReadImageFileExecOptions;
BOOL BeingDebugged;
BOOL Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData
Using rootkit native API redirection methods I hooked ZwQueryInformationProcess to attack
the ProcessDebugPort method and ZwCreateProcessEx so that the PEB member BeginDebugged can
be set to FALSE.
Now the problem we have is that ZwCreateProcessEx is not actually exported from
ntoskern.exe, the closest we can get is NtCreateProcessEx which is exported from ntdll.dll.
So we have two options, we can either
1. Lookup up the address of NtCreateProcessEx from within the driver, and move 1 byte in
from the start address to get the index within KeServiceDescriptorTable
or
2. Manually disassemble ntdll.dll to get the service index for each OS.
I am going to pick option two because i'm lazy, so from the snippet below as you can see the
service index for NtCreateProcess is 30h (Based of XP SP1)
ntdll.dll:77F5B738 ntdll_NtCreateProcessEx:
ntdll.dll:77F5B738 mov eax, 30h
ntdll.dll:77F5B73D mov edx, offset loc_7FFE0300
ntdll.dll:77F5B742 call edx ; loc_7FFE0300
ntdll.dll:77F5B744 retn 24h
debug015:7FFE0300 loc_7FFE0300: ; CODE XREF: ntdll.dll:77F5B742p
debug015:7FFE0300 ; DATA XREF: ntdll.dll:77F5B73Do
debug015:7FFE0300 mov edx, esp
debug015:7FFE0302 sysenter
debug015:7FFE0304 retn
Eliminating NtQueryInformationProcess it quite simple as you can see from the code snippet
below
status = sa.ZwQueryInformationProcess
(ProcessHandle,ProcessInformationClass,ProcessInformation,ProcessInformationLength,ReturnLen
gth);
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 &&
ProcessInformationLength >= 4)
{
DbgPrint ("ZwQueryInformationProcess - ProcessDebugPort request - setting to
NULL\n");
*(ULONG*)ProcessInformation = 0; //forcefuly set port to 0 to that calling
applications
//assumes no debugger is attached
}
}
ZwCreateProcessEx is slightly more complicated because we have to write to the foreign
process address space and set the relevant PEB member to FALSE. There is a DebugPort
parameter to the ZwCreateProcessEx function but I imagine that if you fail to pass this
through onto the real ZwCreateProcessEx then essential debuggee information will not be set
up correctly and the debugger wont function correctly
Interestingly, if you attach a debugger to an application that uses protected WMA's (Windows
Media Player for instance) it still detects the debugger, so there is scope for change to
add support for this. When I find out how it did this then I will update the code.
The code for the article can be found in my vault (anti-debug.c) and is by no means complete
but gives you an idea on how it can be done.
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课