/*
演示HOOK系统服务调用表中的NtOpenProcess函数,保护需要保护的进程被,防止被杀掉
*/
#include<ntddk.h>
/*
KeServiceDescriptorTable仅有ntoskrnel一项,没有包含win32k,而且后面的两个字段都没有使用,所
以为了简便直接把SystemServiceDescriptorTable定义成SYSTEM_SERVICE_TABLE,免得访问多个结构体的
字段,麻烦。这里明白就行了。
*/
typedef struct _SystemServiceDescriptorTable
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;
// KeServiceDescriptorTable为ntoskrnl.exe导出
extern PSystemServiceDescriptorTable KeServiceDescriptorTable;
// 定义一下NtOpenProcess的原型,下面如果用汇编调用就不用定义了,但是我想尽量不用汇编
typedef NTSTATUS (__stdcall *NTOPENPROCESS)( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
NTOPENPROCESS RealNtOpenProcess;
// 定义函数原型
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
// 真实的函数地址,我们会在自定义的函数中调用
ULONG RealServiceAddress;
// 需要被驱动保护的进程ID
HANDLE MyPID;
// 自定义的NtOpenProcess函数
NTSTATUS __stdcall MyNtOpenProcess( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId )
{
NTSTATUS rc;
ULONG PID;
//DbgPrint( "NtOpenProcess() called.\n" );
rc = (NTSTATUS)(NTOPENPROCESS)RealNtOpenProcess( ProcessHandle, DesiredAccess,
ObjectAttributes, ClientId );
if( (ClientId != NULL) )
{
PID = (ULONG)ClientId->UniqueProcess;
//DbgPrint( "%d was opened,Handle is %d.\n", PID, (ULONG)ProcessHandle );
// 如果进程PID是1520,直接返回权限不足,并将句柄设置为空
if( PID == 1520 )
{
DbgPrint( "Some want to open pid 1520!\n" );
ProcessHandle = NULL;
rc = STATUS_ACCESS_DENIED;
}
}
return rc;
}
// 驱动入口
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
DriverObject->DriverUnload = OnUnload;
Hook();
return STATUS_SUCCESS;
}
// 驱动卸载
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
Unhook( );
}
// 此处修改SSDT中的NtOpenProcess服务地址
VOID Hook()
{
ULONG Address;
// 0x7A为Winxp+SP2下NtOpenProcess服务ID号
// Adress是个地址A,这个地址的数据还是一个地址B,这个地址B就是NtOpenProcess的地址了
// (ULONG)KeServiceDescriptorTable->ServiceTableBase就是温家堡的第一个房间
// Address是第7A个房间。
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
// 取得地址A的值,也就是NtOpenProcess服务的地址了,保存原来NtOpenProcess的地址以后恢
复用
RealServiceAddress = *(ULONG*)Address;
RealNtOpenProcess = (NTOPENPROCESS)RealServiceAddress;
DbgPrint( "Address of Real NtOpenProcess: 0x%08X\n", RealServiceAddress );
DbgPrint(" Address of MyNtOpenProcess: 0x%08X\n", MyNtOpenProcess );
// 去掉内存保护,为什么这样就去掉了呢?
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
// 修改SSDT中NtOpenProcess服务的地址
*((ULONG*)Address) = (ULONG)MyNtOpenProcess;
// 恢复内存保护
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
}
//////////////////////////////////////////////////////
VOID Unhook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
// 还原SSDT
*((ULONG*)Address) = (ULONG)RealServiceAddress;
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
DbgPrint("Unhook");
}
看了别人的一段代码,请问为什么
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
就可以去掉windows内存保护了呢····
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课