#include <ntddk.h>
typedef struct _SDT
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
PUCHAR ParamTableBase;
}SDT, *PSDT;
typedef
NTSTATUS
(__stdcall *ZWSETINFORMATIONFILE)(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
extern "C" PSDT KeServiceDescriptorTable; //ntoskrnl.exe导出的
PULONG pFuncSDT; //原函数地址在SSDT中的位置
ZWSETINFORMATIONFILE OriZwSetInformationFile; //原函数地址
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);
VOID Hook();
VOID UnHook();
NTSTATUS MyZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegPath)
{
pDriverObject->DriverUnload = DriverUnload;
Hook();
return STATUS_SUCCESS;
}
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
UnHook();
}
VOID Hook()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwSetInformationFile");
pFuncSDT = KeServiceDescriptorTable->ServiceTableBase +
*PULONG((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OriZwSetInformationFile = ZWSETINFORMATIONFILE(*pFuncSDT);
DbgPrint("OriZwSetInformationFile:%x\r\n", OriZwSetInformationFile);
__asm
{
cli
mov eax,cr0
and eax,not 10000h //清除cr0的WP位
mov cr0,eax
}
*pFuncSDT = (ULONG)MyZwSetInformationFile;
DbgPrint("---Hook---\r\n");
__asm
{
mov eax,cr0
or eax,10000h //恢复cr0的WP位
mov cr0,eax
sti
}
}
VOID UnHook()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*pFuncSDT = (ULONG)OriZwSetInformationFile;
DbgPrint("---UnHook---\r\n");
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
NTSTATUS MyZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT pFileObject;
NTSTATUS ret = ObReferenceObjectByHandle(FileHandle, GENERIC_READ,
*IoFileObjectType, KernelMode, (PVOID*)&pFileObject, 0);
if (NT_SUCCESS(ret))
{
UNICODE_STRING uDosName;
ret = IoVolumeDeviceToDosName(pFileObject->DeviceObject, &uDosName); //XP and later
if (NT_SUCCESS(ret))
{
if (!_wcsicmp(pFileObject->FileName.Buffer, L"\\test.txt") &&
!_wcsicmp(uDosName.Buffer, L"C:"))
{
ExFreePool(uDosName.Buffer);
return STATUS_ACCESS_DENIED;
}
ExFreePool(uDosName.Buffer);
}
}
return OriZwSetInformationFile(FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
}
typedef struct _SDT
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
PUCHAR ParamTableBase;
}SDT, *PSDT;
typedef
NTSTATUS
(__stdcall *ZWSETINFORMATIONFILE)(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
extern "C" PSDT KeServiceDescriptorTable; //ntoskrnl.exe导出的
PULONG pFuncSDT; //原函数地址在SSDT中的位置
ZWSETINFORMATIONFILE OriZwSetInformationFile; //原函数地址
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);
VOID Hook();
VOID UnHook();
NTSTATUS MyZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegPath)
{
pDriverObject->DriverUnload = DriverUnload;
Hook();
return STATUS_SUCCESS;
}
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
UnHook();
}
VOID Hook()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwSetInformationFile");
pFuncSDT = KeServiceDescriptorTable->ServiceTableBase +
*PULONG((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OriZwSetInformationFile = ZWSETINFORMATIONFILE(*pFuncSDT);
DbgPrint("OriZwSetInformationFile:%x\r\n", OriZwSetInformationFile);
__asm
{
cli
mov eax,cr0
and eax,not 10000h //清除cr0的WP位
mov cr0,eax
}
*pFuncSDT = (ULONG)MyZwSetInformationFile;
DbgPrint("---Hook---\r\n");
__asm
{
mov eax,cr0
or eax,10000h //恢复cr0的WP位
mov cr0,eax
sti
}
}
VOID UnHook()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*pFuncSDT = (ULONG)OriZwSetInformationFile;
DbgPrint("---UnHook---\r\n");
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
NTSTATUS MyZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT pFileObject;
NTSTATUS ret = ObReferenceObjectByHandle(FileHandle, GENERIC_READ,
*IoFileObjectType, KernelMode, (PVOID*)&pFileObject, 0);
if (NT_SUCCESS(ret))
{
UNICODE_STRING uDosName;
ret = IoVolumeDeviceToDosName(pFileObject->DeviceObject, &uDosName); //XP and later
if (NT_SUCCESS(ret))
{
if (!_wcsicmp(pFileObject->FileName.Buffer, L"\\test.txt") &&
!_wcsicmp(uDosName.Buffer, L"C:"))
{
ExFreePool(uDosName.Buffer);
return STATUS_ACCESS_DENIED;
}
ExFreePool(uDosName.Buffer);
}
}
return OriZwSetInformationFile(FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
}
本文详细介绍了如何通过修改ZwSetInformationFile函数的实现,实现对特定文件(如\test.txt位于C盘)的访问控制。在Windows内核模式下,利用KeServiceDescriptorTable和OriZwSetInformationFile,作者通过钩子技术改变了原有函数的行为,增加了额外的安全检查逻辑。当尝试访问指定文件时,函数将返回STATUS_ACCESS_DENIED错误,阻止了非法访问。
811

被折叠的 条评论
为什么被折叠?



