For instance i have a code which do transparent encryption on fly whenever any user tries to access a file. Here in this code i did xor operation instead of encryption for simplicity. Here this code works well when reading through type command and writing using notepad. But when you access using notepad it give encrypted content.
#include <fltKernel.h>
#define MOUNT_PREFIX L"\\Device\\HarddiskVolume3\\Mount"
PFLT_FILTER gFilterHandle;
FLT_PREOP_CALLBACK_STATUS EncryptPreWrite(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID* CompletionContext
);
FLT_PREOP_CALLBACK_STATUS EncryptPreRead(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext
);
FLT_POSTOP_CALLBACK_STATUS EncryptPostRead(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext,
FLT_POST_OPERATION_FLAGS Flags
);
NTSTATUS EncryptUnload(FLT_FILTER_UNLOAD_FLAGS Flags);
FLT_POSTOP_CALLBACK_STATUS
EncryptPostCreate(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext,
FLT_POST_OPERATION_FLAGS Flags
);
// register only Write and Read
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, 0, NULL, EncryptPostCreate },
{ IRP_MJ_WRITE, 0, EncryptPreWrite, NULL },
{ IRP_MJ_READ, 0, EncryptPreRead, EncryptPostRead },
{ IRP_MJ_OPERATION_END }
};
CONST FLT_REGISTRATION FilterRegistration = {
sizeof(FLT_REGISTRATION), FLT_REGISTRATION_VERSION, 0, NULL,
Callbacks, EncryptUnload, NULL, NULL, NULL, NULL
};
// simple XOR-by-2
static VOID XorBuffer(PUCHAR buf, ULONG len) {
for (ULONG i = 0; i < len; i++) {
buf[i] ^= 0x02;
}
}
static
BOOLEAN
IsUnderMount(
_In_ PFLT_CALLBACK_DATA Data
)
{
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;
BOOLEAN match = FALSE;
UNICODE_STRING mountPrefix = RTL_CONSTANT_STRING(MOUNT_PREFIX);
status = FltGetFileNameInformation(
Data,
FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo);
if (!NT_SUCCESS(status))
return FALSE;
status = FltParseFileNameInformation(nameInfo);
if (NT_SUCCESS(status)) {
if (RtlPrefixUnicodeString(&mountPrefix, &nameInfo->Name, TRUE)) {
match = TRUE;
}
}
FltReleaseFileNameInformation(nameInfo);
return match;
}
FLT_POSTOP_CALLBACK_STATUS
EncryptPostCreate(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext,
FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);
// only if create succeeded
if (!NT_SUCCESS(Data->IoStatus.Status)) {
return FLT_POSTOP_FINISHED_PROCESSING;
}
// get name
PFLT_FILE_NAME_INFORMATION nameInfo;
if (NT_SUCCESS(FltGetFileNameInformation(
Data,
FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo)) &&
NT_SUCCESS(FltParseFileNameInformation(nameInfo)))
{
UNICODE_STRING mountPrefix = RTL_CONSTANT_STRING(MOUNT_PREFIX);
if (RtlPrefixUnicodeString(&mountPrefix, &nameInfo->Name, TRUE)) {
// flush & purge caches for this file
FltFlushBuffers(FltObjects->Instance,
FltObjects->FileObject);
// ask the I/O manager to re-try the create
Data->IoStatus.Status = STATUS_SUCCESS;
Data->IoStatus.Information = 0;
}
FltReleaseFileNameInformation(nameInfo);
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
FLT_PREOP_CALLBACK_STATUS EncryptPreRead(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (IsUnderMount(Data))
{
KdPrint(("PreRead Called"));
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS
EncryptPreWrite(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID* CompletionContext
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (IsUnderMount(Data))
{
// lock user buffer into memory and get system-space pointer
NTSTATUS sts = FltLockUserBuffer(Data);
if (NT_SUCCESS(sts)) {
PUCHAR buf = Data->Iopb->Parameters.Write.WriteBuffer;
ULONG len = Data->Iopb->Parameters.Write.Length;
if (buf && len) {
XorBuffer(buf, len);
}
}
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS
EncryptPostRead(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PVOID CompletionContext,
FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);
if (IsUnderMount(Data))
{
// lock user buffer into memory and get system-space pointer
NTSTATUS sts = FltLockUserBuffer(Data);
if (NT_SUCCESS(sts)) {
PUCHAR buf = Data->Iopb->Parameters.Read.ReadBuffer;
ULONG len = Data->Iopb->Parameters.Read.Length;
if (buf && len) {
XorBuffer(buf, len);
}
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
//------------------------------------------------------------------------------
// Unload
//------------------------------------------------------------------------------
NTSTATUS
EncryptUnload(
FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(Flags);
FltUnregisterFilter(gFilterHandle);
return STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// DriverEntry (register & start)
//------------------------------------------------------------------------------
NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = FltRegisterFilter(
DriverObject,
&FilterRegistration,
&gFilterHandle
);
if (NT_SUCCESS(status)) {
status = FltStartFiltering(gFilterHandle);
if (!NT_SUCCESS(status)) {
FltUnregisterFilter(gFilterHandle);
}
}
return status;
}