📄 重入问题创建shadow device object.txt
字号:
版主,你好像误解了那个人提出的问题.不光是要将IRP发送到特定的FSD栈里的某一层.而是要在我自己的Filter中Create 文件,而又不重入我的Filter,“老外”的做法是起一个“标志性”的名字,然后在Filter中区分那些文件是我的Filiter要打开的,那些是一般程序要打开的,但是么,这实在不明智。有一种好方法,就是自己建立IRP请求,然后下传。其中用到了一些构建自己的IRP,以及FileObject的方法。
下面是创建避免重入的关键代码,用该代码可以直接构建并下传打开文件的IRP。不过,这只是测试版的代码,如果哪位大侠发现这里的Bug,希望与我联系(li-gen@x263.net),谢谢。另外感谢Smith, Joel 的指导。
NTSTATUS FsSimpleOpen(PUNICODE_STRING pstrName, ACCESS_MASK DesiredAccess, PDEVICE_OBJECT pVolume, PDEVICE_OBJECT pRealDevice, PFILE_OBJECT pParent, PFILE_OBJECT *ppFile)
{
PIRP pIrp = NULL;
PIO_STACK_LOCATION pStack;
KEVENT event;
IO_STATUS_BLOCK stat;
NTSTATUS ntRet;
PFILE_OBJECT pFile = NULL;
OBJECT_ATTRIBUTES oa;
ACCESS_STATE AccessState;
HANDLE hFile = NULL;
IO_SECURITY_CONTEXT ctx;
ULONG *pAuxData = ExAllocatePool(NonPagedPool, 1024);
if (pAuxData == NULL)
{
ntRet = STATUS_INSUFFICIENT_RESOURCES;
CLEANUP();
}
ASSERT(pVolume != NULL);
ASSERT(pRealDevice != NULL);
ASSERT(ppFile != NULL);
ASSERT(pstrName != NULL);
memset(pAuxData, 0, 1024);
//initialize an event and an IRP to send to the fsd
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
pIrp = IoAllocateIrp(pVolume->StackSize, FALSE);
IF_OUTOFMEMORY_CLEANUP(pIrp, &ntRet);
InitializeObjectAttributes(&oa,
NULL,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
//create a file object for the irp
ntRet = ObCreateObject(KernelMode,
*IoFileObjectType,
&oa,
KernelMode,
0,
sizeof(FILE_OBJECT),
0,
0,
&pFile);
IF_FAIL_CLEANUP(ntRet);
//initialize the file object
RtlZeroMemory(pFile, sizeof(FILE_OBJECT));
pFile->Type = IO_TYPE_FILE;
pFile->Size = sizeof(FILE_OBJECT);
pFile->DeviceObject = pRealDevice;
pFile->Flags = FO_SYNCHRONOUS_IO;
pFile->RelatedFileObject = pParent;
//initialize embedded synch objects
KeInitializeEvent(&pFile->Lock, SynchronizationEvent, FALSE);
KeInitializeEvent(&pFile->Event, NotificationEvent, FALSE);
//copy the file name into the buffer
pFile->FileName.Buffer = ExAllocatePool(NonPagedPool, pstrName->MaximumLength);
if (pFile->FileName.Buffer == NULL)
{
ntRet = STATUS_INSUFFICIENT_RESOURCES;
CLEANUP();
}
pFile->FileName.MaximumLength = pstrName->MaximumLength;
pFile->FileName.Length = pstrName->Length;
RtlCopyMemory(pFile->FileName.Buffer, pstrName->Buffer, pstrName->Length);
//setup the irp
pIrp->UserEvent = &event;
pIrp->UserIosb = &stat;
pIrp->Tail.Overlay.Thread = KeGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFile;
pIrp->RequestorMode = KernelMode;
pIrp->Flags |= (IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API);
pIrp->MdlAddress = NULL;
pIrp->PendingReturned = FALSE;
pIrp->Cancel = FALSE;
pIrp->CancelRoutine = NULL;
pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
//Set up the I/O stack location.
pStack = IoGetNextIrpStackLocation(pIrp);
pStack->MajorFunction = IRP_MJ_CREATE;
pStack->DeviceObject = pVolume;
pStack->FileObject = pFile;
//create an access state for the sd
ntRet = SeCreateAccessState(&AccessState, pAuxData, DesiredAccess, IoGetFileObjectGenericMapping());
IF_FAIL_CLEANUP(ntRet);
//fill out the create\'s security context
ctx.AccessState = &AccessState;
ctx.DesiredAccess = DesiredAccess;
ctx.SecurityQos = NULL;
ctx.FullCreateOptions = 0;
//fill out the the create parameter
pStack->Parameters.Create.SecurityContext = &ctx;
pStack->Parameters.Create.Options = FILE_OPEN << 24;
pStack->Parameters.Create.FileAttributes = FILE_ATTRIBUTE_NORMAL;
pStack->Parameters.Create.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
pStack->Parameters.Create.EaLength = 0;
//set the completion routine (that will free the irp)
IoSetCompletionRoutine(pIrp, FsDefaultComplete, 0, TRUE, TRUE, TRUE);
//Send it to the FSD
ntRet = IoCallDriver(pVolume, pIrp);
pIrp = NULL;
if (ntRet == STATUS_PENDING)
{
//wait for the io to complete
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
ntRet = stat.Status;
}
CLEANUP:
SAFE_FREE_POOL(pAuxData);
if (!NT_SUCCESS(ntRet))
{
if (pIrp != NULL)
{
IoFreeIrp(pIrp);
}
if (pFile)
{
SAFE_FREE_POOL(pFile->FileName.Buffer);
pFile->DeviceObject = NULL;
ObDereferenceObject(pFile);
}
}
else
{
FsReferenceDeviceAndVpb(pFile);
//set the out param
*ppFile = pFile;
}
return ntRet;
}
VOID FsReferenceDeviceAndVpb(PFILE_OBJECT pFile)
{
NTSTATUS ntRet;
ASSERT(pFile->Vpb != NULL ? pFile->DeviceObject->Vpb != NULL :
pFile->DeviceObject->Vpb == NULL);
//Increment RealDevice\'s reference count.
InterlockedIncrement(&pFile->DeviceObject->ReferenceCount);
//Increment Vpb\'s reference count, if one exists.
if (pFile->Vpb)
{
ASSERT((pFile->Vpb->Flags & VPB_MOUNTED) && !(pFile->Vpb->Flags & VPB_LOCKED));
InterlockedIncrement(&pFile->Vpb->ReferenceCount);
}
}
我可不想要钱。我还是学生嘛,但是么,我觉得有技术就因该提供。
希望 版主 多提意见。但是如果有哪位未经我同意,把本程序投稿到相管杂志或是本站的资料文章区,来骗取个人利益,我一定饶不了他。
=====================================
BOOLEAN
HookDrive(
IN PDRIVER_OBJECT DriverObject,
IN WCHAR DriveLetter
)
{
IO_STATUS_BLOCK IoStatus;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
PDEVICE_OBJECT FileSysDevice;
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT ShadowDeviceObject;
UNICODE_STRING ShadowDeviceName;
WCHAR ShadowDeviceNameBuffer[] = L"\\Device\\FDFilterShadowA";
UNICODE_STRING FileName;
WCHAR FileNameBuffer[] = L"\\DosDevices\\A:\\";
NTSTATUS Status;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION Pdx;
PDEVICE_EXTENSION ShadowPdx;
//
// Replace the drive letter
//
FileNameBuffer[12] = DriveLetter;
ShadowDeviceNameBuffer[22] = DriveLetter;
//
// We have to figure out what device to hook - first open the volume's
// root directory
//
RtlInitUnicodeString(&FileName, FileNameBuffer);
InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateFile(&FileHandle, 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);
if (!NT_SUCCESS(Status))
{
KdPrint(("fdfilter.sys: Could not open drive: %x\n", Status));
return FALSE;
}
KdPrint(("fdfilter.sys: opened the root directory!!! handle: %x\n", FileHandle));
//
// Got the file handle, so now look-up the file-object it refers to
//
Status = ObReferenceObjectByHandle(FileHandle, FILE_READ_DATA, NULL, KernelMode, &FileObject, NULL);
if (!NT_SUCCESS(Status))
{
KdPrint(("fdfilter.sys: Could not get fileobject from handle\n"));
ZwClose(FileHandle);
return FALSE;
}
//
// Next, find out what device is associated with the file object by getting its related
// device object
//
FileSysDevice = IoGetRelatedDeviceObject(FileObject);
if (!FileSysDevice)
{
KdPrint(("fdfilter.sys: Could not get related device object\n"));
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
return FALSE;
}
//
// Create a shadow device object
//
RtlInitUnicodeString(&ShadowDeviceName, ShadowDeviceNameBuffer);
Status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&ShadowDeviceName,
FileSysDevice->DeviceType,
0,
FALSE,
&ShadowDeviceObject);
if (!NT_SUCCESS(Status))
{
KdPrint(("fdfilter.sys: failed to create associated device\n"));
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
return FALSE;
}
ShadowDeviceObject->StackSize = FileSysDevice->StackSize;
//
// The file system's device hasn't been hooked already, so make a hooking device
// object that will be attached to it.
//
Status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FileSysDevice->DeviceType,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
KdPrint(("fdfilter.sys: failed to create associated device\n"));
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
IoDeleteDevice(ShadowDeviceObject);
return FALSE;
}
//
// Setup the device extensions. The drive letter and file system object are stored
// in the extension.
//
ShadowPdx = ShadowDeviceObject->DeviceExtension;
ShadowPdx->Type = SHADOW;
ShadowPdx->FsDeviceObject = NULL;
ShadowPdx->AttachToDeviceObject = NULL;
ShadowPdx->BuddyDeviceObject = DeviceObject;
Pdx = DeviceObject->DeviceExtension;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -