📄 drivefilter.c
字号:
{
Dump ("Drive filter attached to a volume pdo=%p", filterExtension->Pdo);
if (filterExtension->QueueStarted && EncryptedIoQueueIsRunning (&filterExtension->Queue))
EncryptedIoQueueStop (&filterExtension->Queue);
filterExtension->IsVolumeFilterDevice = TRUE;
filterExtension->IsDriveFilterDevice = FALSE;
}
else if (!BootDriveFound)
{
MountDrive (filterExtension, &BootArgs.BootPassword, &BootArgs.HeaderSaltCrc32);
}
}
}
static VOID MountDriveWorkItemRoutine (PDEVICE_OBJECT deviceObject, DriveFilterExtension *filterExtension)
{
CheckDeviceTypeAndMount (filterExtension);
KeSetEvent (&filterExtension->MountWorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
}
static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension)
{
if (Irp->PendingReturned)
IoMarkIrpPending (Irp);
if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{
CheckDeviceTypeAndMount (Extension);
}
else
{
PIO_WORKITEM workItem = IoAllocateWorkItem (filterDeviceObject);
if (!workItem)
{
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent (&Extension->MountWorkItemCompletedEvent, SynchronizationEvent, FALSE);
IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension);
KeWaitForSingleObject (&Extension->MountWorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
IoFreeWorkItem (workItem);
}
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
return STATUS_CONTINUE_COMPLETION;
}
static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
{
NTSTATUS status;
status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
if (!NT_SUCCESS (status))
return TCCompleteIrp (Irp, status, Irp->IoStatus.Information);
switch (irpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
Dump ("IRP_MN_START_DEVICE pdo=%p\n", Extension->Pdo);
return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension);
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
Dump ("IRP_MN_DEVICE_USAGE_NOTIFICATION type=%d\n", (int) irpSp->Parameters.UsageNotification.Type);
{
PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject);
if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE))
DeviceObject->Flags |= DO_POWER_PAGABLE;
ObDereferenceObject (attachedDevice);
}
// Prevent creation of hibernation and crash dump files
if (irpSp->Parameters.UsageNotification.InPath
&& (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile
|| (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation && !HibernationDriverFilterActive)))
{
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation)
++HibernationPreventionCount;
return TCCompleteIrp (Irp, STATUS_UNSUCCESSFUL, Irp->IoStatus.Information);
}
return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension);
case IRP_MN_REMOVE_DEVICE:
Dump ("IRP_MN_REMOVE_DEVICE pdo=%p\n", Extension->Pdo);
IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp);
status = PassIrp (Extension->LowerDeviceObject, Irp);
IoDetachDevice (Extension->LowerDeviceObject);
if (Extension->QueueStarted && EncryptedIoQueueIsRunning (&Extension->Queue))
EncryptedIoQueueStop (&Extension->Queue);
if (Extension->DriveMounted)
DismountDrive (Extension);
if (Extension->BootDrive)
{
BootDriveFound = FALSE;
BootDriveFilterExtension = NULL;
}
DriverMutexWait();
IoDeleteDevice (DeviceObject);
DriverMutexRelease();
return status;
default:
status = PassIrp (Extension->LowerDeviceObject, Irp);
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
}
return status;
}
static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
{
NTSTATUS status;
Dump ("IRP_MJ_POWER minor=%d type=%d shutdown=%d\n", (int) irpSp->MinorFunction, (int) irpSp->Parameters.Power.Type, (int) irpSp->Parameters.Power.ShutdownType);
if (SetupInProgress
&& irpSp->MinorFunction == IRP_MN_SET_POWER
&& irpSp->Parameters.Power.Type == DevicePowerState
&& irpSp->Parameters.Power.ShutdownType == PowerActionHibernate)
{
EncryptionSetupThreadAbortRequested = TRUE;
ObDereferenceObject (EncryptionSetupThread);
while (SetupInProgress)
TCSleep (200);
}
#if 0 // Dismount of the system drive is disabled until there is a way to do it without causing system errors (see the documentation for more info)
if (DriverShuttingDown
&& Extension->DriveMounted
&& irpSp->MinorFunction == IRP_MN_SET_POWER
&& irpSp->Parameters.Power.Type == DevicePowerState)
{
if (Extension->QueueStarted && EncryptedIoQueueIsRunning (&Extension->Queue))
EncryptedIoQueueStop (&Extension->Queue);
if (Extension->DriveMounted)
DismountDrive (Extension);
}
#endif // 0
PoStartNextPowerIrp (Irp);
status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
if (!NT_SUCCESS (status))
return TCCompleteIrp (Irp, status, Irp->IoStatus.Information);
IoSkipCurrentIrpStackLocation (Irp);
status = PoCallDriver (Extension->LowerDeviceObject, Irp);
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
return status;
}
NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DriveFilterExtension *Extension = (DriveFilterExtension *) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
ASSERT (!Extension->bRootDevice && Extension->IsDriveFilterDevice);
switch (irpSp->MajorFunction)
{
case IRP_MJ_READ:
case IRP_MJ_WRITE:
if (BootDriveFound && !Extension->BootDrive)
{
return PassIrp (Extension->LowerDeviceObject, Irp);
}
else
{
NTSTATUS status = EncryptedIoQueueAddIrp (&Extension->Queue, Irp);
if (status != STATUS_PENDING)
TCCompleteDiskIrp (Irp, status, 0);
return status;
}
case IRP_MJ_PNP:
return DispatchPnp (DeviceObject, Irp, Extension, irpSp);
case IRP_MJ_POWER:
return DispatchPower (DeviceObject, Irp, Extension, irpSp);
default:
return PassIrp (Extension->LowerDeviceObject, Irp);
}
}
void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp)
{
LARGE_INTEGER offset;
char *header;
ReopenBootVolumeHeaderRequest *request = (ReopenBootVolumeHeaderRequest *) irp->AssociatedIrp.SystemBuffer;
irp->IoStatus.Information = 0;
if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice())
{
irp->IoStatus.Status = STATUS_ACCESS_DENIED;
return;
}
if (!ValidateIOBufferSize (irp, sizeof (ReopenBootVolumeHeaderRequest), ValidateInput))
return;
if (!BootDriveFound || !BootDriveFilterExtension || !BootDriveFilterExtension->DriveMounted || !BootDriveFilterExtension->HeaderCryptoInfo
|| request->VolumePassword.Length > MAX_PASSWORD)
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
goto wipe;
}
header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!header)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
goto wipe;
}
if (BootDriveFilterExtension->HiddenSystem)
offset.QuadPart = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
else
offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
irp->IoStatus.Status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!NT_SUCCESS (irp->IoStatus.Status))
{
Dump ("TCReadDevice error %x\n", irp->IoStatus.Status);
goto ret;
}
if (ReadVolumeHeader (!BootDriveFilterExtension->HiddenSystem, header, &request->VolumePassword, NULL, BootDriveFilterExtension->HeaderCryptoInfo) == 0)
{
Dump ("Header reopened\n");
BootDriveFilterExtension->Queue.CryptoInfo->header_creation_time = BootDriveFilterExtension->HeaderCryptoInfo->header_creation_time;
BootDriveFilterExtension->Queue.CryptoInfo->pkcs5 = BootDriveFilterExtension->HeaderCryptoInfo->pkcs5;
BootDriveFilterExtension->Queue.CryptoInfo->noIterations = BootDriveFilterExtension->HeaderCryptoInfo->noIterations;
irp->IoStatus.Status = STATUS_SUCCESS;
}
else
{
crypto_close (BootDriveFilterExtension->HeaderCryptoInfo);
BootDriveFilterExtension->HeaderCryptoInfo = NULL;
Dump ("Header not reopened\n");
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
ret:
TCfree (header);
wipe:
burn (request, sizeof (*request));
}
typedef NTSTATUS (*HiberDriverWriteFunctionA) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3);
typedef NTSTATUS (*HiberDriverWriteFunctionB) (PLARGE_INTEGER writeOffset, PMDL dataMdl);
typedef struct
{
// Until MS releases an API for filtering hibernation drivers, we have to resort to this.
#ifdef _WIN64
byte FieldPad1[64];
HiberDriverWriteFunctionB WriteFunctionB;
byte FieldPad2[56];
#else
byte FieldPad1[48];
HiberDriverWriteFunctionB WriteFunctionB;
byte FieldPad2[32];
#endif
HiberDriverWriteFunctionA WriteFunctionA;
byte FieldPad3[24];
LARGE_INTEGER PartitionStartOffset;
} HiberDriverContext;
typedef NTSTATUS (*HiberDriverEntry) (PVOID arg0, HiberDriverContext *hiberDriverContext);
typedef struct
{
LIST_ENTRY ModuleList;
#ifdef _WIN64
byte FieldPad1[32];
#else
byte FieldPad1[16];
#endif
PVOID ModuleBaseAddress;
HiberDriverEntry ModuleEntryAddress;
#ifdef _WIN64
byte FieldPad2[24];
#else
byte FieldPad2[12];
#endif
UNICODE_STRING ModuleName;
} ModuleTableItem;
#define TC_MAX_HIBER_FILTER_COUNT 3
static int LastHiberFilterNumber = 0;
static HiberDriverEntry OriginalHiberDriverEntries[TC_MAX_HIBER_FILTER_COUNT];
static HiberDriverWriteFunctionA OriginalHiberDriverWriteFunctionsA[TC_MAX_HIBER_FILTER_COUNT];
static HiberDriverWriteFunctionB OriginalHiberDriverWriteFunctionsB[TC_MAX_HIBER_FILTER_COUNT];
static LARGE_INTEGER HiberPartitionOffset;
static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER writeOffset, PMDL dataMdl, BOOL writeB, ULONG arg0WriteA, PVOID arg3WriteA)
{
MDL *encryptedDataMdl = dataMdl;
if (writeOffset && dataMdl && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted)
{
ULONG dataLength = MmGetMdlByteCount (dataMdl);
if (dataMdl->MappedSystemVa && dataLength > 0)
{
uint64 offset = HiberPartitionOffset.QuadPart + writeOffset->QuadPart;
uint64 intersectStart;
uint32 intersectLength;
if (dataLength > TC_HIBERNATION_WRITE_BUFFER_SIZE)
TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW);
if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
GetIntersection (offset,
dataLength,
BootDriveFilterExtension->Queue.EncryptedAreaStart,
BootDriveFilterExtension->Queue.EncryptedAreaEnd,
&intersectStart,
&intersectLength);
if (intersectLength > 0)
{
UINT64_STRUCT dataUnit;
dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
memcpy (HibernationWriteBuffer, dataMdl->MappedSystemVa, dataLength);
if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset;
EncryptDataUnitsCurrentThread (HibernationWriteBuffer + (intersectStart - offset),
&dataUnit,
intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
BootDriveFilterExtension->Queue.CryptoInfo);
encryptedDataMdl = HibernationWriteBufferMdl;
MmInitializeMdl (encryptedDataMdl, HibernationWriteBuffer, dataLength);
encryptedDataMdl->MdlFlags = dataMdl->MdlFlags;
}
}
}
if (writeB)
return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl);
return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA);
}
static NTSTATUS HiberDriverWriteFunctionAFilter0 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
{
return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, FALSE, arg0, arg3);
}
static NTSTATUS HiberDriverWriteFunctionAFilter1 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
{
return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, FALSE, arg0, arg3);
}
static NTSTATUS HiberDriverWriteFunctionAFilter2 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
{
return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, FALSE, arg0, arg3);
}
static NTSTATUS HiberDriverWriteFunctionBFilter0 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
{
return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, TRUE, 0, NULL);
}
static NTSTATUS HiberDriverWriteFunctionBFilter1 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
{
return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, TRUE, 0, NULL);
}
static NTSTATUS HiberDriverWriteFunctionBFilter2 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
{
return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, TRUE, 0, NULL);
}
static NTSTATUS HiberDriverEntryFilter (int filterNumber, PVOID arg0, HiberDriverContext *hiberDriverContext)
{
BOOL filterInstalled = FALSE;
NTSTATUS status;
if (!OriginalHiberDriverEntries[filterNumber])
return STATUS_UNSUCCESSFUL;
status = (*OriginalHiberDriverEntries[filterNumber]) (arg0, hiberDriverContext);
if (!NT_SUCCESS (status) || !hiberDriverContext)
return status;
if (SetupInProgress)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
if (hiberDriverContext->WriteFunctionA)
{
Dump ("Filtering WriteFunctionA %d\n", filterNumber);
OriginalHiberDriverWriteFunctionsA[filterNumber] = hiberDriverContext->WriteFunctionA;
switch (filterNumber)
{
case 0: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter0; break;
case 1: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter1; break;
case 2: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter2; break;
default: TC_THROW_FATAL_EXCEPTION;
}
filterInstalled = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -