📄 drivefilter.c
字号:
if (hiberDriverContext->WriteFunctionB)
{
Dump ("Filtering WriteFunctionB %d\n", filterNumber);
OriginalHiberDriverWriteFunctionsB[filterNumber] = hiberDriverContext->WriteFunctionB;
switch (filterNumber)
{
case 0: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter0; break;
case 1: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter1; break;
case 2: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter2; break;
default: TC_THROW_FATAL_EXCEPTION;
}
filterInstalled = TRUE;
}
if (filterInstalled && hiberDriverContext->PartitionStartOffset.QuadPart != 0)
{
HiberPartitionOffset = hiberDriverContext->PartitionStartOffset;
if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
hiberDriverContext->PartitionStartOffset.QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset;
}
return STATUS_SUCCESS;
}
static NTSTATUS HiberDriverEntryFilter0 (PVOID arg0, HiberDriverContext *hiberDriverContext)
{
return HiberDriverEntryFilter (0, arg0, hiberDriverContext);
}
static NTSTATUS HiberDriverEntryFilter1 (PVOID arg0, HiberDriverContext *hiberDriverContext)
{
return HiberDriverEntryFilter (1, arg0, hiberDriverContext);
}
static NTSTATUS HiberDriverEntryFilter2 (PVOID arg0, HiberDriverContext *hiberDriverContext)
{
return HiberDriverEntryFilter (2, arg0, hiberDriverContext);
}
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)
{
if (moduleItem->ModuleName.Buffer && moduleItem->ModuleName.Length >= 5 * sizeof (wchar_t))
{
// Skip MS BitLocker filter
if (moduleItem->ModuleName.Length >= 13 * sizeof (wchar_t)
&& memcmp (moduleItem->ModuleName.Buffer, L"hiber_dumpfve", 13 * sizeof (wchar_t)) == 0)
break;
if (memcmp (moduleItem->ModuleName.Buffer, L"hiber", 5 * sizeof (wchar_t)) == 0
|| memcmp (moduleItem->ModuleName.Buffer, L"Hiber", 5 * sizeof (wchar_t)) == 0
|| memcmp (moduleItem->ModuleName.Buffer, L"HIBER", 5 * sizeof (wchar_t)) == 0)
{
HiberDriverEntry filterEntry;
switch (LastHiberFilterNumber)
{
case 0: filterEntry = HiberDriverEntryFilter0; break;
case 1: filterEntry = HiberDriverEntryFilter1; break;
case 2: filterEntry = HiberDriverEntryFilter2; break;
default: TC_THROW_FATAL_EXCEPTION;
}
if (moduleItem->ModuleEntryAddress != filterEntry)
{
// Install filter
OriginalHiberDriverEntries[LastHiberFilterNumber] = moduleItem->ModuleEntryAddress;
moduleItem->ModuleEntryAddress = filterEntry;
if (++LastHiberFilterNumber > TC_MAX_HIBER_FILTER_COUNT - 1)
LastHiberFilterNumber = 0;
}
}
}
break;
}
}
KeLowerIrql (origIrql);
}
void StartHibernationDriverFilter ()
{
PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
NTSTATUS status;
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (!TCDriverObject->DriverSection || !*(ModuleTableItem **) TCDriverObject->DriverSection)
goto err;
// All buffers required for hibernation must be allocated here
#ifdef _WIN64
highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFULL;
#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;
// Make sure volume header can be updated
if (Extension->HeaderCryptoInfo == NULL)
{
SetupResult = STATUS_INVALID_PARAMETER;
goto ret;
}
buffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
if (!buffer)
{
SetupResult = STATUS_INSUFFICIENT_RESOURCES;
goto ret;
}
if (SetupRequest.SetupMode == SetupEncryption && SetupRequest.WipeAlgorithm != TC_WIPE_NONE)
{
wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
if (!wipeBuffer)
{
SetupResult = STATUS_INSUFFICIENT_RESOURCES;
goto ret;
}
}
while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 1000)))
{
if (EncryptionSetupThreadAbortRequested)
goto abort;
TransformWaitingForIdle = TRUE;
}
TransformWaitingForIdle = FALSE;
switch (SetupRequest.SetupMode)
{
case SetupEncryption:
Dump ("Encrypting...\n");
if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1)
{
// Start encryption
Extension->Queue.EncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart;
Extension->Queue.EncryptedAreaEnd = -1;
offset.QuadPart = Extension->ConfiguredEncryptedAreaStart;
}
else
{
// Resume aborted encryption
if (Extension->Queue.EncryptedAreaEnd == Extension->ConfiguredEncryptedAreaEnd)
goto err;
offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1;
}
break;
case SetupDecryption:
Dump ("Decrypting...\n");
if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1)
{
SetupResult = STATUS_SUCCESS;
goto abort;
}
offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1;
break;
default:
goto err;
}
EncryptedIoQueueResumeFromHold (&Extension->Queue);
Dump ("EncryptedAreaStart=%I64d\n", Extension->Queue.EncryptedAreaStart);
Dump ("EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaEnd);
Dump ("ConfiguredEncryptedAreaStart=%I64d\n", Extension->ConfiguredEncryptedAreaStart);
Dump ("ConfiguredEncryptedAreaEnd=%I64d\n", Extension->ConfiguredEncryptedAreaEnd);
Dump ("offset=%I64d\n", offset.QuadPart);
Dump ("EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024);
while (!EncryptionSetupThreadAbortRequested)
{
if (SetupRequest.SetupMode == SetupEncryption)
{
if (offset.QuadPart + setupBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1)
setupBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart);
if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd)
break;
}
else
{
if (offset.QuadPart - setupBlockSize < Extension->Queue.EncryptedAreaStart)
setupBlockSize = (ULONG) (offset.QuadPart - Extension->Queue.EncryptedAreaStart);
offset.QuadPart -= setupBlockSize;
if (setupBlockSize == 0 || offset.QuadPart < Extension->Queue.EncryptedAreaStart)
break;
}
while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500)))
{
if (EncryptionSetupThreadAbortRequested)
goto abort;
TransformWaitingForIdle = TRUE;
}
TransformWaitingForIdle = FALSE;
status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
if (!NT_SUCCESS (status))
{
Dump ("TCReadDevice error %x offset=%I64d\n", status, offset.QuadPart);
if (SetupRequest.ZeroUnreadableSectors && SetupRequest.SetupMode == SetupEncryption)
{
// Zero unreadable sectors
uint64 zeroedSectorCount;
status = ZeroUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, offset, setupBlockSize, &zeroedSectorCount);
if (!NT_SUCCESS (status))
{
SetupResult = status;
goto err;
}
// Retry read
status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
if (!NT_SUCCESS (status))
{
SetupResult = status;
goto err;
}
}
else
{
SetupResult = status;
goto err;
}
}
dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE;
if (SetupRequest.SetupMode == SetupEncryption)
{
EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
if (SetupRequest.WipeAlgorithm != TC_WIPE_NONE)
{
byte wipePass;
for (wipePass = 1; wipePass <= GetWipePassCount (SetupRequest.WipeAlgorithm); ++wipePass)
{
if (!WipeBuffer (SetupRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, setupBlockSize))
{
ULONG i;
for (i = 0; i < setupBlockSize; ++i)
{
wipeBuffer[i] = buffer[i] + wipePass;
}
EncryptDataUnits (wipeBuffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate));
}
status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, setupBlockSize);
if (!NT_SUCCESS (status))
{
// Undo failed write operation
DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
SetupResult = status;
goto err;
}
}
memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate));
}
}
else
{
DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
}
status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
if (!NT_SUCCESS (status))
{
Dump ("TCWriteDevice error %x\n", status);
// Undo failed write operation
if (SetupRequest.SetupMode == SetupEncryption)
DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
else
EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
SetupResult = status;
goto err;
}
if (SetupRequest.SetupMode == SetupEncryption)
offset.QuadPart += setupBlockSize;
Extension->Queue.EncryptedAreaEnd = offset.QuadPart - 1;
headerUpdateRequired = TRUE;
EncryptedIoQueueResumeFromHold (&Extension->Queue);
KeAcquireSpinLock (&SetupStatusSpinLock, &irql);
SetupStatusEncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd;
KeReleaseSpinLock (&SetupStatusSpinLock, irql);
// Update volume header
bytesWrittenSinceHeaderUpdate += setupBlockSize;
if (bytesWrittenSinceHeaderUpdate >= TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD)
{
status = SaveDriveVolumeHeader (Extension);
if (!NT_SUCCESS (status))
{
SetupResult = status;
goto err;
}
headerUpdateRequired = FALSE;
bytesWrittenSinceHeaderUpdate = 0;
}
}
abort:
SetupResult = STATUS_SUCCESS;
err:
if (Extension->Queue.EncryptedAreaEnd == -1)
Extension->Queue.EncryptedAreaStart = -1;
if (EncryptedIoQueueIsSuspended (&Extension->Queue))
EncryptedIoQueueResumeFromHold (&Extension->Queue);
if (SetupRequest.SetupMode == SetupDecryption && Extension->Queue.EncryptedAreaStart >= Extension->Queue.EncryptedAreaEnd)
{
while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 0)));
Extension->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaEnd = -1;
Extension->Queue.EncryptedAreaStart = Extension->Queue.EncryptedAreaEnd = -1;
EncryptedIoQueueResumeFromHold (&Extension->Queue);
headerUpdateRequired = TRUE;
}
Dump ("Setup completed: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd);
if (headerUpdateRequired)
{
status = SaveDriveVolumeHeader (Extension);
if (!NT_SUCCESS (status) && NT_SUCCESS (SetupResult))
SetupResult = status;
}
if (SetupRequest.SetupMode == SetupDecryption && Extension->ConfiguredEncryptedAreaEnd == -1 && Extension->DriveMounted)
{
DismountDrive (Extension);
}
ret:
if (buffer)
TCfree (buffer);
if (wipeBuffer)
TCfree (wipeBuffer);
SetupInProgress = FALSE;
PsTerminateSystemThread (SetupResult);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -