【半原创】Irp占坑保护文件不被删除

Irp操作出自125096的博客

http://blog.csdn.net/qq125096885/article/details/53033896


这里提下 博主的例子中使用irpclose文件对象,这可能会造成蓝屏。

见链接:https://bbs.pediy.com/thread-215269.htm

所以这里把IrpCloseFile改为ObDereferenceObject即可


但是如果是需要实现无法删除,那么就不需要调用ObDereferenceObject

原因你猜~

此方法使用Irp去删除是无法删除的~

见代码~

#include <ntddk.h>  

#ifndef MAX_PATH  
#define MAX_PATH          260  
#endif  

NTSTATUS ObOpenObjectByPointer(PVOID Object, ULONG HandleAttributes, PACCESS_STATE PassedAccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PHANDLE Handle);
NTSTATUS ObCreateObject(KPROCESSOR_MODE ProbeMode, POBJECT_TYPE ObjectType, POBJECT_ATTRIBUTES ObjectAttributes, KPROCESSOR_MODE OwnershipMode, PVOID ParseContext, ULONG ObjectBodySize, ULONG PagedPoolCharge, ULONG NonPagedPoolCharge, PVOID *Object);
NTSTATUS SeCreateAccessState(PACCESS_STATE AccessState, PVOID AuxData, ACCESS_MASK DesiredAccess, PGENERIC_MAPPING GenericMapping);

typedef struct _AUX_ACCESS_DATA {
	PPRIVILEGE_SET PrivilegesUsed;
	GENERIC_MAPPING GenericMapping;
	ACCESS_MASK AccessesToAudit;
	ACCESS_MASK MaximumAuditMask;
	ULONG Unknown[256];
} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;

//获取设备对象  
NTSTATUS GetDriveObject(PUNICODE_STRING pDriveName, PDEVICE_OBJECT *DeviceObject, PDEVICE_OBJECT *ReadDevice);

//IRP打开文件  
NTSTATUS IrpCreateFile(PUNICODE_STRING pFilePath, ACCESS_MASK DesiredAccess, PIO_STATUS_BLOCK pIoStatusBlock, PFILE_OBJECT *pFileObject);


VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	return;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS status;
	DriverObject->DriverUnload = DriverUnload;

	UNICODE_STRING strFilePath;
	IO_STATUS_BLOCK IoStatusBlock = { 0 };
	PFILE_OBJECT pFileObject = NULL;
	RtlInitUnicodeString(&strFilePath, L"\\??\\c:\\test.exe");

	//打开文件  
	status = IrpCreateFile(&strFilePath, GENERIC_READ | DELETE, &IoStatusBlock, &pFileObject);
	if (NT_SUCCESS(status))
	{
		//关闭文件  发irp close会触发内存重复释放 应使用ObDereferenceObject
		// 如果不ObDereferenceObject 除关机.磁盘填0(怎么获取偏移是一个问题~)之外 无法删除文件
		// ObDereferenceObject(pFileObject);
	}
	return STATUS_SUCCESS;
}


//完成历程  
NTSTATUS IoCompletionRoutineEx(PDEVICE_OBJECT  DeviceObject, PIRP  Irp, PVOID  Context)
{

	*Irp->UserIosb = Irp->IoStatus;
	if (Irp->UserEvent)
		KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0);

	if (Irp->MdlAddress)
	{
		IoFreeMdl(Irp->MdlAddress);
		Irp->MdlAddress = NULL;
	}

	IoFreeIrp(Irp);
	return STATUS_MORE_PROCESSING_REQUIRED;

}

//获取设备对象  
NTSTATUS GetDriveObject(PUNICODE_STRING pDriveName, PDEVICE_OBJECT *DeviceObject, PDEVICE_OBJECT *ReadDevice)
{

	//定义变量  
	NTSTATUS status;
	OBJECT_ATTRIBUTES objectAttributes;
	HANDLE DeviceHandle = NULL;
	IO_STATUS_BLOCK ioStatus;
	PFILE_OBJECT pFileObject;

	//参数效验  
	if (pDriveName == NULL || DeviceObject == NULL || ReadDevice == NULL)return STATUS_INVALID_PARAMETER;

	//  \\??\\C:  
	//打开设备  
	InitializeObjectAttributes(&objectAttributes, pDriveName, OBJ_CASE_INSENSITIVE, NULL, NULL);
	status = IoCreateFile(&DeviceHandle, SYNCHRONIZE | FILE_ANY_ACCESS, &objectAttributes, &ioStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
	if (!NT_SUCCESS(status))return status;

	//获取文件对象  
	status = ObReferenceObjectByHandle(DeviceHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, &pFileObject, NULL);
	if (!NT_SUCCESS(status))
	{
		ZwClose(DeviceHandle);
		return status;
	}

	//效验结果  
	if (pFileObject->Vpb == 0 || pFileObject->Vpb->RealDevice == NULL)
	{
		ObDereferenceObject(pFileObject);
		ZwClose(DeviceHandle);
		return STATUS_UNSUCCESSFUL;
	}

	//设置变量  
	*DeviceObject = pFileObject->Vpb->DeviceObject;
	*ReadDevice = pFileObject->Vpb->RealDevice;

	ObDereferenceObject(pFileObject);
	ZwClose(DeviceHandle);


	return STATUS_SUCCESS;
}

//IRP打开文件  
NTSTATUS IrpCreateFile(PUNICODE_STRING pFilePath, ACCESS_MASK DesiredAccess, PIO_STATUS_BLOCK pIoStatusBlock, PFILE_OBJECT *pFileObject)
{
	NTSTATUS ntStatus;
	PIRP pIrp;
	KEVENT kEvent;
	static ACCESS_STATE AccessState;
	static AUX_ACCESS_DATA AuxData;
	OBJECT_ATTRIBUTES ObjectAttributes;
	PFILE_OBJECT  pNewFileObject;
	IO_SECURITY_CONTEXT SecurityContext;
	PIO_STACK_LOCATION IrpSp;
	PDEVICE_OBJECT pDeviceObject = NULL;
	PDEVICE_OBJECT pReadDevice = NULL;
	UNICODE_STRING DriveName;
	wchar_t* pFileNameBuf = NULL;
	static wchar_t szFilePath[MAX_PATH] = { 0 };
#define SYMBOLICLINKLENG            6           //  \\??\\c:            \\windows\\notepad.exe  


	if (pFilePath == NULL || pIoStatusBlock == NULL || pFileObject == NULL || pFilePath->Length <= SYMBOLICLINKLENG)return STATUS_INVALID_PARAMETER;

	RtlZeroMemory(szFilePath, sizeof(szFilePath));
	RtlCopyMemory(szFilePath, pFilePath->Buffer, (SYMBOLICLINKLENG + 1) * sizeof(wchar_t));
	RtlInitUnicodeString(&DriveName, szFilePath);


	ntStatus = GetDriveObject(&DriveName, &pDeviceObject, &pReadDevice);
	if (!NT_SUCCESS(ntStatus))return ntStatus;

	RtlZeroMemory(szFilePath, sizeof(szFilePath));
	RtlCopyMemory(szFilePath, &pFilePath->Buffer[SYMBOLICLINKLENG], pFilePath->Length - SYMBOLICLINKLENG);
	RtlInitUnicodeString(&DriveName, szFilePath);
	pFileNameBuf = ExAllocatePool(NonPagedPool, DriveName.MaximumLength);
	if (pFileNameBuf == NULL)return STATUS_UNSUCCESSFUL;
	RtlZeroMemory(pFileNameBuf, DriveName.MaximumLength);
	RtlCopyMemory(pFileNameBuf, DriveName.Buffer, DriveName.Length);

	if (pDeviceObject == NULL || pReadDevice == NULL || pDeviceObject->StackSize <= 0)return STATUS_UNSUCCESSFUL;

	InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL);
	ntStatus = ObCreateObject(KernelMode, *IoFileObjectType, &ObjectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, &pNewFileObject);
	if (!NT_SUCCESS(ntStatus))return ntStatus;

	pIrp = IoAllocateIrp(pDeviceObject->StackSize, FALSE);
	if (pIrp == NULL)
	{
		ObDereferenceObject(pNewFileObject);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
	RtlZeroMemory(pNewFileObject, sizeof(FILE_OBJECT));
	pNewFileObject->Type = IO_TYPE_FILE;
	pNewFileObject->Size = sizeof(FILE_OBJECT);
	pNewFileObject->DeviceObject = pReadDevice;
	pNewFileObject->Flags = FO_SYNCHRONOUS_IO;
	RtlInitUnicodeString(&pNewFileObject->FileName, pFileNameBuf);
	KeInitializeEvent(&pNewFileObject->Lock, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pNewFileObject->Event, NotificationEvent, FALSE);

	ntStatus = SeCreateAccessState(&AccessState, &AuxData, DesiredAccess, IoGetFileObjectGenericMapping());
	if (!NT_SUCCESS(ntStatus))
	{
		IoFreeIrp(pIrp);
		ObDereferenceObject(pNewFileObject);
		return ntStatus;
	}


	SecurityContext.SecurityQos = NULL;
	SecurityContext.AccessState = &AccessState;
	SecurityContext.DesiredAccess = DesiredAccess;
	SecurityContext.FullCreateOptions = 0;

	pIrp->MdlAddress = NULL;
	pIrp->AssociatedIrp.SystemBuffer = NULL;
	pIrp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
	pIrp->RequestorMode = KernelMode;
	pIrp->UserIosb = pIoStatusBlock;
	pIrp->UserEvent = &kEvent;
	pIrp->PendingReturned = FALSE;
	pIrp->Cancel = FALSE;
	pIrp->CancelRoutine = NULL;
	pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
	pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
	pIrp->Tail.Overlay.OriginalFileObject = pNewFileObject;

	IrpSp = IoGetNextIrpStackLocation(pIrp);
	IrpSp->MajorFunction = IRP_MJ_CREATE;
	IrpSp->DeviceObject = pDeviceObject;
	IrpSp->FileObject = pNewFileObject;
	IrpSp->Parameters.Create.SecurityContext = &SecurityContext;
	IrpSp->Parameters.Create.Options = (FILE_OPEN_IF << 24) | 0;
	IrpSp->Parameters.Create.FileAttributes = FILE_ATTRIBUTE_NORMAL;
	IrpSp->Parameters.Create.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
	IrpSp->Parameters.Create.EaLength = 0;

	IoSetCompletionRoutine(pIrp, IoCompletionRoutineEx, 0, TRUE, TRUE, TRUE);
	ntStatus = IoCallDriver(pDeviceObject, pIrp);
	if (ntStatus == STATUS_PENDING)
		KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);
	ntStatus = pIoStatusBlock->Status;

	if (!NT_SUCCESS(ntStatus))
	{
		pNewFileObject->DeviceObject = NULL;
		ObDereferenceObject(pNewFileObject);
	}
	else
	{
		InterlockedIncrement(&pNewFileObject->DeviceObject->ReferenceCount);
		if (pNewFileObject->Vpb)
			InterlockedIncrement(&pNewFileObject->Vpb->ReferenceCount);
		*pFileObject = pNewFileObject;

		//ObDereferenceObject(pNewFileObject);  
	}

	return ntStatus;
}

删除的思路

1.找到这个FileObject ObDereferenceObject~

2.找跟句柄、对象无关的删除方法~




猜你喜欢

转载自blog.csdn.net/zhuhuibeishadiao/article/details/78050887