Send IRP_MJ_SET_INFORMATION from DispatchWrite

All good morning! The task is to write at zero-size file preliminary 4-bytes signature and to set endoffile in 4, then to skip irp further. Thus in a cache signature should not be, only on a disk. So, at first i receive IRP with flags 0xa00 - I skip it, marking for myself that with given FCB I will work. If I have correctly understood all, it is writing in a cache. Afterwards behind it there is a IRP with flags 0x43 - (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO). It, obviously, writing directly on a disk. In it I also insert the signature. So, I create IRP_MJ_WRITE with the signature, and after it send IRP_MJ_SET_INFORMATION, to shift end of a file on 4 units forwards. After all it I shift in parametres initial irp on 4 offset on which record will be carried out and easy I transfer control further. What problems - record like passes normally (status_success, and information=4) while precisely has not checked up since the data from a cache which in any case skips the signature further is permanently read. And here with shifting the end of a file of a problem - in IoStatus all on zero, i.e. no information is written. It also confirms the subsequent interception IRP_MJ_SET_INFORMATION which the system sends after original record. Here a code from DispatchWrite:

KeInitializeEvent(&event2, SynchronizationEvent, FALSE);
MyIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
if(!MyIrp)
{
return ERROR_CREATE_IRP;
}
MyBuffer=(PVOID)ExAllocatePool(NonPagedPool,BUFFER_SIZE);
MyIrp->AssociatedIrp.SystemBuffer=MyBuffer;
if(pDiskDeviceExtension->DiskDeviceObject->Flags & DO_DIRECT_IO)
{
MyMDL=IoAllocateMdl(
MyBuffer,
4,
FALSE,
FALSE, // TRUE for highest level driver
MyIrp
);
if(MyMDL==NULL)
{
return ERROR_CREATE_IRP;
}
// MmBuildMdlForNonPagedPool(MyMDL);
// MmProbeAndLockPages(MyMDL, KernelMode,IoReadAccess);
}
MyIrp->UserEvent = &event2;
MyIrp->UserBuffer=MyBuffer;
MyIrp->Cancel=FALSE;
MyIrp->UserIosb = &IoStatusBlock;
MyIrp->Tail.Overlay.Thread = PsGetCurrentThread();
MyIrp->Tail.Overlay.OriginalFileObject = p_IO_STK->FileObject;
MyIrp->RequestorMode = KernelMode; // changed
MyIrp->Flags |= (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO);

RtlCopyMemory(MyBuffer,“ABCD”,4);
if(MyMDL!=NULL)
{
MmBuildMdlForNonPagedPool(MyMDL);
}
IoSetNextIrpStackLocation(MyIrp);
p_IO_NextSTK = IoGetCurrentIrpStackLocation(MyIrp);

p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;

p_IO_NextSTK =IoGetNextIrpStackLocation(MyIrp);
p_IO_NextSTK->MajorFunction=IRP_MJ_WRITE;
p_IO_NextSTK->MinorFunction = 0;
p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;
p_IO_NextSTK->Parameters.Write.Length = 4;
p_IO_NextSTK->Parameters.Write.ByteOffset.QuadPart = 0;

IoSetCompletionRoutine(MyIrp,
OnCreateWriteCompletion,
&DeviceObject,
TRUE,
TRUE,
TRUE);

IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject,MyIrp);

KeWaitForSingleObject(&event2, Executive, KernelMode, TRUE, 0);
KeClearEvent(&event2);

// ??? ??? ??? ???

KeInitializeEvent(&event2, SynchronizationEvent, FALSE);
MyIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
if(!MyIrp)
{
return ERROR_CREATE_IRP;
}
MyBuffer=(PVOID)ExAllocatePool(NonPagedPool,sizeof(FILE_END_OF_FILE_INFORMATION));
((PFILE_END_OF_FILE_INFORMATION)MyBuffer)->EndOfFile.QuadPart=4;
MyIrp->AssociatedIrp.SystemBuffer=MyBuffer;
MyIrp->UserEvent = &event2;
MyIrp->UserBuffer=MyBuffer;
MyIrp->Cancel=FALSE;
MyIrp->UserIosb = &IoStatusBlock;
MyIrp->Tail.Overlay.Thread = PsGetCurrentThread();
MyIrp->Tail.Overlay.OriginalFileObject = p_IO_STK->FileObject;
MyIrp->RequestorMode = KernelMode;
// MyIrp->Flags = 0;
MyIrp->Flags |= (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO);

IoSetNextIrpStackLocation(MyIrp);

p_IO_NextSTK =IoGetNextIrpStackLocation(MyIrp);
p_IO_NextSTK->MajorFunction=IRP_MJ_SET_INFORMATION;
p_IO_NextSTK->MinorFunction = 0;
p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;
p_IO_NextSTK->Parameters.SetFile.FileObject=0;
p_IO_NextSTK->Parameters.SetFile.Length=sizeof(FILE_END_OF_FILE_INFORMATION);
p_IO_NextSTK->Parameters.SetFile.ReplaceIfExists=FALSE;
p_IO_NextSTK->Parameters.SetFile.AdvanceOnly=TRUE;
p_IO_NextSTK->Parameters.SetFile.FileInformationClass=FileEndOfFileInformation;

IoSetCompletionRoutine(MyIrp,
OnSetCompletion,
&DeviceObject,
TRUE,
TRUE,
TRUE);

IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject,MyIrp);

KeWaitForSingleObject(&event2, Executive, KernelMode, TRUE, 0);
KeClearEvent(&event2);
if(p_IO_STK->Parameters.Write.ByteOffset.HighPart != -1)
{
p_IO_STK->Parameters.Write.ByteOffset.QuadPart+=4;
p_IO_STK->FileObject->CurrentByteOffset.QuadPart+=4;
}

After such a thing, all further paging/noncached IO will come misaligned to the disk.

You must add an integral number of sectors, of switch your design to the layered FSD.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
All good morning! The task is to write at zero-size file preliminary 4-bytes signature and to set endoffile in 4, then to skip irp further. Thus in a cache signature should not be, only on a disk. So, at first i receive IRP with flags 0xa00 - I skip it, marking for myself that with given FCB I will work. If I have correctly understood all, it is writing in a cache. Afterwards behind it there is a IRP with flags 0x43 - (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO). It, obviously, writing directly on a disk. In it I also insert the signature. So, I create IRP_MJ_WRITE with the signature, and after it send IRP_MJ_SET_INFORMATION, to shift end of a file on 4 units forwards. After all it I shift in parametres initial irp on 4 offset on which record will be carried out and easy I transfer control further. What problems - record like passes normally (status_success, and information=4) while precisely has not checked up since the data from a cache which in any case skips the signature further is permanently read. And here with shifting the end of a file of a problem - in IoStatus all on zero, i.e. no information is written. It also confirms the subsequent interception IRP_MJ_SET_INFORMATION which the system sends after original record. Here a code from DispatchWrite:

KeInitializeEvent(&event2, SynchronizationEvent, FALSE);
MyIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
if(!MyIrp)
{
return ERROR_CREATE_IRP;
}
MyBuffer=(PVOID)ExAllocatePool(NonPagedPool,BUFFER_SIZE);
MyIrp->AssociatedIrp.SystemBuffer=MyBuffer;
if(pDiskDeviceExtension->DiskDeviceObject->Flags & DO_DIRECT_IO)
{
MyMDL=IoAllocateMdl(
MyBuffer,
4,
FALSE,
FALSE, // TRUE for highest level driver
MyIrp
);
if(MyMDL==NULL)
{
return ERROR_CREATE_IRP;
}
// MmBuildMdlForNonPagedPool(MyMDL);
// MmProbeAndLockPages(MyMDL, KernelMode,IoReadAccess);
}
MyIrp->UserEvent = &event2;
MyIrp->UserBuffer=MyBuffer;
MyIrp->Cancel=FALSE;
MyIrp->UserIosb = &IoStatusBlock;
MyIrp->Tail.Overlay.Thread = PsGetCurrentThread();
MyIrp->Tail.Overlay.OriginalFileObject = p_IO_STK->FileObject;
MyIrp->RequestorMode = KernelMode; // changed
MyIrp->Flags |= (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO);

RtlCopyMemory(MyBuffer,“ABCD”,4);
if(MyMDL!=NULL)
{
MmBuildMdlForNonPagedPool(MyMDL);
}
IoSetNextIrpStackLocation(MyIrp);
p_IO_NextSTK = IoGetCurrentIrpStackLocation(MyIrp);

p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;

p_IO_NextSTK =IoGetNextIrpStackLocation(MyIrp);
p_IO_NextSTK->MajorFunction=IRP_MJ_WRITE;
p_IO_NextSTK->MinorFunction = 0;
p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;
p_IO_NextSTK->Parameters.Write.Length = 4;
p_IO_NextSTK->Parameters.Write.ByteOffset.QuadPart = 0;

IoSetCompletionRoutine(MyIrp,
OnCreateWriteCompletion,
&DeviceObject,
TRUE,
TRUE,
TRUE);

IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject,MyIrp);

KeWaitForSingleObject(&event2, Executive, KernelMode, TRUE, 0);
KeClearEvent(&event2);

// ??? ??? ??? ???

KeInitializeEvent(&event2, SynchronizationEvent, FALSE);
MyIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
if(!MyIrp)
{
return ERROR_CREATE_IRP;
}
MyBuffer=(PVOID)ExAllocatePool(NonPagedPool,sizeof(FILE_END_OF_FILE_INFORMATION));
((PFILE_END_OF_FILE_INFORMATION)MyBuffer)->EndOfFile.QuadPart=4;
MyIrp->AssociatedIrp.SystemBuffer=MyBuffer;
MyIrp->UserEvent = &event2;
MyIrp->UserBuffer=MyBuffer;
MyIrp->Cancel=FALSE;
MyIrp->UserIosb = &IoStatusBlock;
MyIrp->Tail.Overlay.Thread = PsGetCurrentThread();
MyIrp->Tail.Overlay.OriginalFileObject = p_IO_STK->FileObject;
MyIrp->RequestorMode = KernelMode;
// MyIrp->Flags = 0;
MyIrp->Flags |= (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO);

IoSetNextIrpStackLocation(MyIrp);

p_IO_NextSTK =IoGetNextIrpStackLocation(MyIrp);
p_IO_NextSTK->MajorFunction=IRP_MJ_SET_INFORMATION;
p_IO_NextSTK->MinorFunction = 0;
p_IO_NextSTK->DeviceObject = DeviceObject;
p_IO_NextSTK->FileObject=p_IO_STK->FileObject;
p_IO_NextSTK->Parameters.SetFile.FileObject=0;
p_IO_NextSTK->Parameters.SetFile.Length=sizeof(FILE_END_OF_FILE_INFORMATION);
p_IO_NextSTK->Parameters.SetFile.ReplaceIfExists=FALSE;
p_IO_NextSTK->Parameters.SetFile.AdvanceOnly=TRUE;
p_IO_NextSTK->Parameters.SetFile.FileInformationClass=FileEndOfFileInformation;

IoSetCompletionRoutine(MyIrp,
OnSetCompletion,
&DeviceObject,
TRUE,
TRUE,
TRUE);

IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject,MyIrp);

KeWaitForSingleObject(&event2, Executive, KernelMode, TRUE, 0);
KeClearEvent(&event2);
if(p_IO_STK->Parameters.Write.ByteOffset.HighPart != -1)
{
p_IO_STK->Parameters.Write.ByteOffset.QuadPart+=4;
p_IO_STK->FileObject->CurrentByteOffset.QuadPart+=4;
}

Can you tell me more exactly, what should i add/change? Sorry, but i don’t understand Your post fully

You cannot add non-sector-aligned header this way.

The thing is that, after such, all noncached/paging IO will become non-sector-aligned, which is usually a failure.

Personally, I would keep the metadata in some separate files (probably in a hidden directory), not in the main files.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> Can you tell me more exactly, what should i add/change? Sorry, but i don’t understand Your post fully
>

Maxim S. Shatskih wrote:

You cannot add non-sector-aligned header this way.

The thing is that, after such, all noncached/paging IO will become non-sector-aligned, which is usually a failure.

Personally, I would keep the metadata in some separate files (probably in a hidden directory), not in the main files.

The problem with keeping it in a separate file is that things like CSC
(Client Side Caching) break.

Pete


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

I skip all operations with metadata and process only previously crypted files. So I have refused this idea, because everything work correctly even without this setting endoffile.
Now i have working encrypting driver, which works correctly with all popular programs. But i have one problem - when i execute some antivirus or antirootkit program, for example gmer, rootkit unhooker or dr.web, my system freeze. WinDbg say:

Access violation - code c0000005 (!!! second chance !!!)
nt!RtlUnicodeToMultiByteN+0xec:
805885e8 0fb7581c movzx ebx,word ptr [eax+1Ch]
*** ERROR: Module load completed but symbols could not be loaded for gmer.sys

Does anybody know, whats may be wrong? TIA