Hi,
I have written a testing-purpose filter driver based on FileMon. It
decrypts/encrypts *.DWG files only when AutoCAD(acad.exe) accesses them.
It doesn’t change file size.
I track the DWG files using FileObj->FsContext. After IRP_MJ_CREATE
succeeds, add it to tracking structure, while after IRP_MJ_CLOSE, decrease
the reference count. Decrypt the data in-place after IRP_MJ_READ and
encrypt the data using my own IRP before IRP_MJ_WRITE is passed down to
lower driver.
But AutoCAD still says “Corrupt file” when it tries to open an DWG
file(This file is already encrypted with a little tool before my driver
starts).
Did I miss sth.? I post the source. Hope gurus can help me out. Thx!
//------------------------------------------------------------------------
//procedure for IRP_MJ_READ
NTSTATUS CheckReadIRP(PDEVICE_OBJECT HookDevice, IN PIRP Irp)
{
PMDL ReadBufferMdl;
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
nextIrpStack = IoGetNextIrpStackLocation(Irp);
fileObject = currentIrpStack->FileObject;
hookExt = HookDevice->DeviceExtension;
if (! fileObject)
{
goto PassThrough;
}
if(!(hookExt->Hooked) || !ProcessNameOffset)
{
goto PassThrough;
}
if (! IsProcessNameMatched())
{
goto PassThrough;
}
//Check the tracking structure
if (! IsFileObjInTrackList(fileObject) || ! FilterOn)
{
goto PassThrough;
}
ReadBufferMdl = NULL;
if (((hookExt->FileSystem->Flags & DO_BUFFERED_IO) == 0)
&& ((hookExt->FileSystem->Flags & DO_DIRECT_IO) == 0))
{
if (Irp->MdlAddress)
{
ReadBufferMdl = Irp->MdlAddress;
}
else if (Irp->UserBuffer)
{
ReadBufferMdl = IoAllocateMdl(Irp->UserBuffer,
currentIrpStack->Parameters.Read.Length,
FALSE, FALSE, NULL);
if (ReadBufferMdl)
{
__try
{
MmProbeAndLockPages(ReadBufferMdl, KernelMode, IoModifyAccess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(ReadBufferMdl);
ReadBufferMdl = NULL;
}
}
}
}
*nextIrpStack = *currentIrpStack;
IoSetCompletionRoutine( Irp, SpecialReadCompletionRoutine,
(PVOID)ReadBufferMdl, TRUE, TRUE, TRUE );
return IoCallDriver( hookExt->FileSystem, Irp );
PassThrough:
*nextIrpStack = *currentIrpStack;
IoSetCompletionRoutine( Irp, FilemonHookDone, NULL, TRUE, TRUE, TRUE
);
return IoCallDriver( hookExt->FileSystem, Irp );
}
//-----------------------------------------------------------------------
//completion procedure for IRP_MJ_READ
NTSTATUS SpecialReadCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN
PIRP Irp,
IN PVOID Context )
{
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION currentIrpStack;
PHOOK_EXTENSION hookExt;
char *Data;
DWORD Len;
PMDL ReadBufferMdl;
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
if (! NT_SUCCESS(Irp->IoStatus.Status))
{
return Irp->IoStatus.Status;
}
Len = Irp->IoStatus.Information;
if (Len == 0)
{
return Irp->IoStatus.Status;
}
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = currentIrpStack->FileObject;
hookExt = DeviceObject->DeviceExtension;
if ((hookExt->FileSystem->Flags & DO_BUFFERED_IO) &&
(Irp->AssociatedIrp.SystemBuffer))
{
Data = Irp->AssociatedIrp.SystemBuffer;
GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
}
else if ((hookExt->FileSystem->Flags & DO_DIRECT_IO) &&
(Irp->MdlAddress))
{
Data = MmGetSystemAddressForMdl(Irp->MdlAddress);
if (Data)
{
//Data += MmGetMdlByteOffset(Irp->MdlAddress);
GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
}
}
else if (((hookExt->FileSystem->Flags & DO_BUFFERED_IO) == 0)
&& ((hookExt->FileSystem->Flags & DO_DIRECT_IO) == 0)
//&& (Irp->UserBuffer)
)
{
ReadBufferMdl = (PMDL)Context;
if (ReadBufferMdl)
{
Data = MmGetSystemAddressForMdl(ReadBufferMdl);
if (Data)
{
//Data += MmGetMdlByteOffset(ReadBufferMdl);
GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
}
if (Irp->MdlAddress == NULL)
{
MmUnlockPages(ReadBufferMdl);
IoFreeMdl(ReadBufferMdl);
}
}
}
return Irp->IoStatus.Status;
}