📄 drivefilter.c
字号:
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;
}
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -