📄 drivefilter.c
字号:
}
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 (DriverShuttingDown
&& Extension->DriveMounted
&& irpSp->MinorFunction == IRP_MN_SET_POWER
&& irpSp->Parameters.Power.Type == DevicePowerState)
{
Dump ("IRP_MN_SET_POWER\n");
if (Extension->QueueStarted && EncryptedIoQueueIsRunning (&Extension->Queue))
EncryptedIoQueueStop (&Extension->Queue);
if (Extension->DriveMounted)
DismountDrive (Extension);
}
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 (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (ReopenBootVolumeHeaderRequest))
{
irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
return;
}
if (!BootDriveFound || !BootDriveFilterExtension || !BootDriveFilterExtension->DriveMounted)
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
goto wipe;
}
header = TCalloc (HEADER_SIZE);
if (!header)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
goto wipe;
}
offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
irp->IoStatus.Status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, header, offset, HEADER_SIZE);
if (!NT_SUCCESS (irp->IoStatus.Status))
{
Dump ("TCReadDevice error %x\n", irp->IoStatus.Status);
goto ret;
}
if (VolumeReadHeader (TRUE, 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 (*HiberDriverAtapiWriteRoutine) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3);
typedef NTSTATUS (*HiberDriverScsiWriteRoutine) (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];
HiberDriverScsiWriteRoutine ScsiWriteRoutine;
byte FieldPad2[56];
#else
byte FieldPad1[48];
HiberDriverScsiWriteRoutine ScsiWriteRoutine;
byte FieldPad2[32];
#endif
HiberDriverAtapiWriteRoutine AtapiWriteRoutine;
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;
static HiberDriverEntry OriginalHiberDriverEntry = NULL;
static HiberDriverAtapiWriteRoutine OriginalHiberDriverAtapiWriteRoutine = NULL;
static HiberDriverScsiWriteRoutine OriginalHiberDriverScsiWriteRoutine = NULL;
static LARGE_INTEGER HiberPartitionOffset;
static NTSTATUS HiberDriverWriteRoutineFilter (PLARGE_INTEGER writeOffset, PMDL dataMdl, BOOL scsi, ULONG atapiArg0, PVOID atapiArg3)
{
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);
EncryptDataUnits (HibernationWriteBuffer + (intersectStart - offset),
&dataUnit,
intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
BootDriveFilterExtension->Queue.CryptoInfo);
encryptedDataMdl = HibernationWriteBufferMdl;
MmInitializeMdl (encryptedDataMdl, HibernationWriteBuffer, dataLength);
}
}
}
if (scsi)
return (*OriginalHiberDriverScsiWriteRoutine) (writeOffset, encryptedDataMdl);
return (*OriginalHiberDriverAtapiWriteRoutine) (atapiArg0, writeOffset, encryptedDataMdl, atapiArg3);
}
static NTSTATUS HiberDriverAtapiWriteRoutineFilter (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
{
return HiberDriverWriteRoutineFilter (writeOffset, dataMdl, FALSE, arg0, arg3);
}
static NTSTATUS HiberDriverScsiWriteRoutineFilter (PLARGE_INTEGER writeOffset, PMDL dataMdl)
{
return HiberDriverWriteRoutineFilter (writeOffset, dataMdl, TRUE, 0, NULL);
}
static NTSTATUS HiberDriverEntryFilter (PVOID arg0, HiberDriverContext *hiberDriverContext)
{
NTSTATUS status;
if (!OriginalHiberDriverEntry)
return STATUS_UNSUCCESSFUL;
status = (*OriginalHiberDriverEntry) (arg0, hiberDriverContext);
if (!NT_SUCCESS (status) || !hiberDriverContext)
return status;
if (SetupInProgress)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
if (hiberDriverContext->AtapiWriteRoutine)
{
OriginalHiberDriverAtapiWriteRoutine = hiberDriverContext->AtapiWriteRoutine;
hiberDriverContext->AtapiWriteRoutine = HiberDriverAtapiWriteRoutineFilter;
}
if (hiberDriverContext->ScsiWriteRoutine)
{
OriginalHiberDriverScsiWriteRoutine = hiberDriverContext->ScsiWriteRoutine;
hiberDriverContext->ScsiWriteRoutine = HiberDriverScsiWriteRoutineFilter;
}
HiberPartitionOffset = hiberDriverContext->PartitionStartOffset;
return STATUS_SUCCESS;
}
static VOID LoadImageNotifyRoutine (PUNICODE_STRING fullImageName, HANDLE processId, PIMAGE_INFO imageInfo)
{
ModuleTableItem *moduleItem;
LIST_ENTRY *listEntry;
KIRQL origIrql;
if (!imageInfo || !imageInfo->SystemModeImage || !imageInfo->ImageBase || !TCDriverObject->DriverSection)
return;
moduleItem = *(ModuleTableItem **) TCDriverObject->DriverSection;
if (!moduleItem || !moduleItem->ModuleList.Flink)
return;
// Search loaded system modules for hibernation driver
origIrql = KeRaiseIrqlToDpcLevel();
for (listEntry = moduleItem->ModuleList.Flink->Blink;
listEntry && listEntry != TCDriverObject->DriverSection;
listEntry = listEntry->Flink)
{
moduleItem = CONTAINING_RECORD (listEntry, ModuleTableItem, ModuleList);
if (moduleItem && imageInfo->ImageBase == moduleItem->ModuleBaseAddress)
{
KeLowerIrql (origIrql);
if (moduleItem->ModuleName.Length > 0 && moduleItem->ModuleName.Buffer)
{
static wchar_t *hiberDriverNames[] =
{
L"hiber_ataport.sys",
L"hiber_storport.sys",
L"hiber_scsiport.sys",
NULL
};
static wchar_t *hiberDriverNamesBeforeVista[] =
{
L"hiber_atapi.sys",
L"hiber_scsi.sys",
L"hiber_atapiport.sys",
L"hiber_scsiport.sys",
L"hiber_storport.sys",
NULL
};
wchar_t **hiberDriverName = OsMajorVersion < 6 ? hiberDriverNamesBeforeVista : hiberDriverNames;
while (*hiberDriverName != NULL)
{
UNICODE_STRING hiberDriverNameStr;
RtlInitUnicodeString (&hiberDriverNameStr, *hiberDriverName);
if (RtlCompareUnicodeString (&hiberDriverNameStr, &moduleItem->ModuleName, TRUE) == 0)
{
if (moduleItem->ModuleEntryAddress != HiberDriverEntryFilter)
{
Dump ("Installing filter for %ls\n", *hiberDriverName);
OriginalHiberDriverEntry = moduleItem->ModuleEntryAddress;
moduleItem->ModuleEntryAddress = HiberDriverEntryFilter;
}
break;
}
++hiberDriverName;
}
}
break;
}
}
if (KeGetCurrentIrql() != origIrql)
KeLowerIrql (origIrql);
}
void StartHibernationDriverFilter ()
{
PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
NTSTATUS status;
if (!TCDriverObject->DriverSection || !*(ModuleTableItem **) TCDriverObject->DriverSection)
goto err;
// All buffers required for hibernation must be allocated here
#ifdef _WIN64
highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFffffFFFFULL;
#else
highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFULL;
#endif
HibernationWriteBuffer = MmAllocateContiguousMemory (TC_HIBERNATION_WRITE_BUFFER_SIZE, highestAcceptableWriteBufferAddr);
if (!HibernationWriteBuffer)
goto err;
HibernationWriteBufferMdl = IoAllocateMdl (HibernationWriteBuffer, TC_HIBERNATION_WRITE_BUFFER_SIZE, FALSE, FALSE, NULL);
if (!HibernationWriteBufferMdl)
goto err;
MmBuildMdlForNonPagedPool (HibernationWriteBufferMdl);
status = PsSetLoadImageNotifyRoutine (LoadImageNotifyRoutine);
if (!NT_SUCCESS (status))
goto err;
HibernationDriverFilterActive = TRUE;
return;
err:
HibernationDriverFilterActive = FALSE;
if (HibernationWriteBufferMdl)
{
IoFreeMdl (HibernationWriteBufferMdl);
HibernationWriteBufferMdl = NULL;
}
if (HibernationWriteBuffer)
{
MmFreeContiguousMemory (HibernationWriteBuffer);
HibernationWriteBuffer = NULL;
}
}
static VOID SetupThreadProc (PVOID threadArg)
{
DriveFilterExtension *Extension = BootDriveFilterExtension;
LARGE_INTEGER offset;
UINT64_STRUCT dataUnit;
ULONG setupBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE;
BOOL headerUpdateRequired = FALSE;
int64 bytesWrittenSinceHeaderUpdate = 0;
byte *buffer = NULL;
byte *wipeBuffer = NULL;
byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT];
byte wipeRandCharsUpdate[TC_WIPE_RAND_CHAR_COUNT];
KIRQL irql;
NTSTATUS status;
SetupResult = STATUS_UNSUCCESSFUL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -