#include "ntddk.h"
#define MaxBuf 1024
#define MAXPATHLEN 1024
#define NT_DEVICE_NAME L"\\Device\\ProtectRegistryValueKey"
#define DOS_DEVICE_NAME L"\\DosDevices\\ProtectRegistryValueKey"
#define IOCTL_PROTECT_CONTROL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
#pragma pack(1) //SSDT表的结构
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
/*这个是查询某个函数的地址的一个宏*/
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
NTSYSAPI
NTSTATUS
NTAPI
ObQueryNameString(
IN PVOID Object,
PUNICODE_STRING Name,
ULONG MaximumLength,
PULONG ActualLength
);
///////////////////////////////////////////////////////////
NTSYSAPI
NTSTATUS
NTAPI
ZwSetValueKey(IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
);
typedef NTSTATUS (*ZWSETVALUEKEY)(IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
);
ZWSETVALUEKEY RealZwSetValueKey;
/////////////////////////////////////////////////////////
PVOID GetPointer( HANDLE handle )
{
PVOID pKey;
DbgPrint("*******Enter GetPointer()*******\n");
if(!handle) return NULL;
//取得指针
if( ObReferenceObjectByHandle( handle, 0, NULL, KernelMode, &pKey, NULL ) != STATUS_SUCCESS )
{
pKey = NULL;
}
DbgPrint("*******Leave GetPointer()*******\n");
return pKey;
}
NTSTATUS HookZwSetValueKey( IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize)
{
NTSTATUS rc;
UNICODE_STRING *pUniName; //定义得到修改注册表的UNI路径
ULONG actualLen;
ANSI_STRING keyname,
akeyname,
m_keyname,
m_akeyname; //定义得到修改注册表的UNI路径
PVOID pKey;
RtlUnicodeStringToAnsiString( &akeyname, ValueName, TRUE);
RtlUnicodeStringToAnsiString( &m_akeyname, ValueName, TRUE);
RtlUpperString(&akeyname,&m_akeyname);
RtlFreeAnsiString(&m_akeyname);
DbgPrint("*******Enter HookZwSetValueKey()*******\n");
if( pKey = GetPointer( KeyHandle))
{
pUniName = ExAllocatePool( NonPagedPool, 512*2+2*sizeof(ULONG));
pUniName->MaximumLength = 512*2;
if( NT_SUCCESS( ObQueryNameString( pKey, pUniName, MAXPATHLEN, &actualLen)))
{
RtlUnicodeStringToAnsiString( &keyname, pUniName, TRUE);
keyname.Buffer=_strupr(keyname.Buffer);
akeyname.Buffer=_strupr(akeyname.Buffer);
RtlUnicodeStringToAnsiString( &m_keyname, pUniName, TRUE);
RtlUpperString(&keyname,&m_keyname);
RtlFreeAnsiString(&m_keyname);
DbgPrint("===在这里调用strcmp函数用来比较注册表的键值是否是 \\REGISTRY\\MACHINE\\SOFTWARE\\TEST \n");
if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\TEST") == 0)
{
if(strcmp(akeyname.Buffer,"TEST") ==0)
{
RtlFreeAnsiString(&akeyname);
RtlFreeAnsiString(&keyname);
//下面的2个return语句都是我经过测试的了。但为什么不能够保护注册表的这个对应键值呢?
return 0;
//return STATUS_ACCESS_DENIED;
}
}
RtlFreeAnsiString(&keyname);
}
}
RtlFreeAnsiString(&akeyname);
DbgPrint("调用 rc=RealZwSetValueKey(KeyHandle,ValueName,TitleIndex,Type,Data,DataSize);\n");
rc=RealZwSetValueKey(KeyHandle,ValueName,TitleIndex,Type,Data,DataSize);
DbgPrint("*******Leave HookZwSetValueKey()*******\n");
return rc;
}
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
//卸载时会调用
UNICODE_STRING DeviceLinkString;
PDEVICE_OBJECT DeviceObjectTemp1=NULL;
PDEVICE_OBJECT DeviceObjectTemp2=NULL;
DbgPrint("驱动程序卸载...\n");
RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&DeviceLinkString);
if(DriverObject)
{
DeviceObjectTemp1=DriverObject->DeviceObject;
while(DeviceObjectTemp1)
{
DeviceObjectTemp2=DeviceObjectTemp1;
DeviceObjectTemp1=DeviceObjectTemp1->NextDevice;
IoDeleteDevice(DeviceObjectTemp2);
}
}
DbgPrint("设备已经卸载\n");
DbgPrint("修复SSDT表\n");
_asm
{
cli
mov eax,cr0
and eax,not 10000h //清除cr0的WP位
mov cr0,eax
}
(ZWSETVALUEKEY)(SYSTEMSERVICE(ZwSetValueKey)) =RealZwSetValueKey;
_asm
{
mov eax,cr0
or eax,not 10000h //恢复cr0的WP位
mov cr0,eax
sti
}
DbgPrint("驱动卸载完毕.\n");
}
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
DbgPrint("*****Enter DispatchCreate()\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("*****Leave DispatchCreate()\n");
return Irp->IoStatus.Status;
}
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
DbgPrint("*****Enter DispatchClose()\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("*****Leave DispatchClose()\n");
return Irp->IoStatus.Status;
}
NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
NTSTATUS nStatus = STATUS_SUCCESS;
ULONG IoControlCode = 0;
PIO_STACK_LOCATION IrpStack = NULL;
PCHAR buffer = NULL;
PMDL mdl = NULL;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch(IoControlCode)
{
case IOCTL_PROTECT_CONTROL:
DbgPrint("**********************************\n");
DbgPrint("IOCTL_PROTECT_CONTROL 被调用,通讯成功!\n");
DbgPrint("**********************************\n");
break;
default:
DbgPrint("未知请求包被调用\n");
nStatus = STATUS_INVALID_VARIANT;
break;
}
nStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return nStatus;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING theRegistryPath)
{
//驱动入口函数
NTSTATUS ntStatus = STATUS_SUCCESS;
UNICODE_STRING ntDeviceName;
UNICODE_STRING DeviceLinkString;
PDEVICE_OBJECT deviceObject = NULL;
DbgPrint("驱动程序加载...\n");
RtlInitUnicodeString( &ntDeviceName, NT_DEVICE_NAME );
ntStatus = IoCreateDevice(
DriverObject,
0,
&ntDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrint("无法创建驱动设备");
return ntStatus;
}
RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);
ntStatus=IoCreateSymbolicLink(&DeviceLinkString,&ntDeviceName);
if(!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] =DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = OnUnload;
DbgPrint("驱动程序已经启动\n");
DbgPrint("修改SSDT表...\n");
_asm
{
cli
mov eax,cr0
and eax,not 10000h //清除cr0的WP位
mov cr0,eax
}
//保存原始的内核函数 ZwSetValueKey的地址
RealZwSetValueKey =(ZWSETVALUEKEY)(SYSTEMSERVICE(ZwSetValueKey));
(ZWSETVALUEKEY)(SYSTEMSERVICE(ZwSetValueKey)) = HookZwSetValueKey;
_asm
{
mov eax,cr0
or eax,not 10000h //恢复cr0的WP位
mov cr0,eax
sti
}
DbgPrint("驱动程序加载完毕.\n");
return STATUS_SUCCESS;
}
驱动程序是不会蓝屏了,也可以加载,可以和应用层一起配合运行。假设在我的XP 32位系统下有一个注册表项 \\REGISTRY\\MACHINE\\SOFTWARE\\TEST, 它的键值为TEST
那么在HookZwSetValueKey函数里面,在if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\TEST") == 0)语句块里面
无论我设置return 的返回值为return 0; 还是设置为return STATUS_ACCESS_DENIED;
为什么不能够保护注册表的这个对应键值呢? 即这个键值还是可以被修改、被删除。
请问大家,HookZwSetValueKey函数代码里面有写错吗?
哪里写的不对了?
还是return 值用的不对?
如果不对,应该改成什么?
谢谢了!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课