📄 encryptedioqueue.c
字号:
switch (subFragment)
{
case 0:
subFragmentLength = (ULONG) request->EncryptedOffset;
break;
case 1:
subFragmentOffset.QuadPart += request->EncryptedOffset + queue->RemappedAreaOffset;
subFragmentLength = request->EncryptedLength;
break;
case 2:
subFragmentOffset.QuadPart += request->EncryptedOffset + request->EncryptedLength;
subFragmentLength = (ULONG) (request->Length - (request->EncryptedOffset + request->EncryptedLength));
break;
}
if (subFragmentLength > 0)
{
if (request->Item->Write)
request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, subFragmentData, subFragmentOffset, subFragmentLength);
else
request->Item->Status = TCCachedRead (queue, NULL, subFragmentData, subFragmentOffset, subFragmentLength);
subFragmentData += subFragmentLength;
}
}
}
else
{
// Remap the fragment
LARGE_INTEGER remappedOffset;
remappedOffset.QuadPart = request->Offset.QuadPart + queue->RemappedAreaOffset;
if (request->Item->Write)
request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, remappedOffset, request->Length);
else
request->Item->Status = TCCachedRead (queue, NULL, request->Data, remappedOffset, request->Length);
}
}
else
{
if (request->Item->Write)
request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, request->Offset, request->Length);
else
request->Item->Status = TCCachedRead (queue, NULL, request->Data, request->Offset, request->Length);
}
}
else
{
IO_STATUS_BLOCK ioStatus;
if (request->Item->Write)
request->Item->Status = ZwWriteFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, request->Data, request->Length, &request->Offset, NULL);
else
request->Item->Status = TCCachedRead (queue, &ioStatus, request->Data, request->Offset, request->Length);
if (NT_SUCCESS (request->Item->Status) && ioStatus.Information != request->Length)
request->Item->Status = STATUS_END_OF_FILE;
}
}
if (request->Item->Write)
{
queue->ReadAheadBufferValid = FALSE;
ReleaseFragmentBuffer (queue, request->Data);
if (request->CompleteOriginalIrp)
{
CompleteOriginalIrp (request->Item, request->Item->Status,
NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0);
}
else
{
InterlockedDecrement (&request->Item->OutstandingRequestCount);
KeSetEvent (&queue->RequestCompletedEvent, IO_DISK_INCREMENT, FALSE);
}
ReleasePoolBuffer (queue, request);
}
else
{
BOOL readAhead = FALSE;
if (NT_SUCCESS (request->Item->Status))
memcpy (request->OrigDataBufferFragment, request->Data, request->Length);
ReleaseFragmentBuffer (queue, request->Data);
request->Data = request->OrigDataBufferFragment;
if (request->CompleteOriginalIrp
&& queue->LastReadLength > 0
&& NT_SUCCESS (request->Item->Status)
&& InterlockedExchangeAdd (&queue->IoThreadPendingRequestCount, 0) == 0)
{
readAhead = TRUE;
InterlockedIncrement (&queue->OutstandingIoCount);
}
ExInterlockedInsertTailList (&queue->CompletionThreadQueue, &request->CompletionListEntry, &queue->CompletionThreadQueueLock);
KeSetEvent (&queue->CompletionThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);
if (readAhead)
{
queue->ReadAheadBufferValid = FALSE;
queue->ReadAheadOffset.QuadPart = queue->LastReadOffset.QuadPart + queue->LastReadLength;
queue->ReadAheadLength = queue->LastReadLength;
#ifdef TC_TRACE_IO_QUEUE
Dump ("A %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), queue->ReadAheadOffset, queue->ReadAheadLength);
#endif
if (queue->ReadAheadOffset.QuadPart + queue->ReadAheadLength <= queue->MaxReadAheadOffset.QuadPart)
{
if (queue->IsFilterDevice)
{
queue->ReadAheadBufferValid = NT_SUCCESS (TCReadDevice (queue->LowerDeviceObject, queue->ReadAheadBuffer, queue->ReadAheadOffset, queue->ReadAheadLength));
}
else
{
IO_STATUS_BLOCK ioStatus;
queue->ReadAheadBufferValid = NT_SUCCESS (ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, queue->ReadAheadBuffer, queue->ReadAheadLength, &queue->ReadAheadOffset, NULL));
queue->ReadAheadLength = (ULONG) ioStatus.Information;
}
}
DecrementOutstandingIoCount (queue);
}
}
}
}
PsTerminateSystemThread (STATUS_SUCCESS);
}
static VOID MainThreadProc (PVOID threadArg)
{
EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg;
PLIST_ENTRY listEntry;
EncryptedIoQueueItem *item;
LARGE_INTEGER fragmentOffset;
ULONG dataRemaining;
PUCHAR activeFragmentBuffer = queue->FragmentBufferA;
PUCHAR dataBuffer;
EncryptedIoRequest *request;
uint64 intersectStart;
uint32 intersectLength;
int64 mdlWaitTime;
LARGE_INTEGER mdlWaitPerfCounter;
if (IsEncryptionThreadPoolRunning())
KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
while (!queue->ThreadExitRequested)
{
if (!NT_SUCCESS (KeWaitForSingleObject (&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL)))
continue;
while ((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue, &queue->MainThreadQueueLock)))
{
PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry);
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
if (queue->Suspended)
KeWaitForSingleObject (&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL);
item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem));
if (!item)
{
EncryptedIoQueueItem stackItem;
stackItem.Queue = queue;
stackItem.OriginalIrp = irp;
stackItem.Status = STATUS_INSUFFICIENT_RESOURCES;
TCCompleteDiskIrp (irp, STATUS_INSUFFICIENT_RESOURCES, 0);
OnItemCompleted (&stackItem, FALSE);
continue;
}
item->Queue = queue;
item->OriginalIrp = irp;
item->OutstandingRequestCount = 0;
item->Status = STATUS_SUCCESS;
IoSetCancelRoutine (irp, NULL);
if (irp->Cancel)
{
CompleteOriginalIrp (item, STATUS_CANCELLED, 0);
continue;
}
switch (irpSp->MajorFunction)
{
case IRP_MJ_READ:
item->Write = FALSE;
item->OriginalOffset = irpSp->Parameters.Read.ByteOffset;
item->OriginalLength = irpSp->Parameters.Read.Length;
break;
case IRP_MJ_WRITE:
item->Write = TRUE;
item->OriginalOffset = irpSp->Parameters.Write.ByteOffset;
item->OriginalLength = irpSp->Parameters.Write.Length;
break;
default:
CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
continue;
}
#ifdef TC_TRACE_IO_QUEUE
item->OriginalIrpOffset = item->OriginalOffset;
#endif
// Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices
if (queue->IsFilterDevice
&& !item->Write
&& item->OriginalLength > 0
&& (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0
&& (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
{
byte *buffer;
ULONG alignedLength = item->OriginalLength + ENCRYPTION_DATA_UNIT_SIZE;
LARGE_INTEGER alignedOffset;
alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1);
buffer = TCalloc (alignedLength);
if (!buffer)
{
CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
continue;
}
item->Status = TCReadDevice (queue->LowerDeviceObject, buffer, alignedOffset, alignedLength);
if (NT_SUCCESS (item->Status))
{
UINT64_STRUCT dataUnit;
dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority);
if (!dataBuffer)
{
TCfree (buffer);
CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
continue;
}
if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd != -1)
{
GetIntersection (alignedOffset.QuadPart, alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength);
if (intersectLength > 0)
{
dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
}
}
memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength);
}
TCfree (buffer);
CompleteOriginalIrp (item, item->Status, NT_SUCCESS (item->Status) ? item->OriginalLength : 0);
continue;
}
// Validate offset and length
if (item->OriginalLength == 0
|| (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
|| (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
|| (!queue->IsFilterDevice && item->OriginalOffset.QuadPart + item->OriginalLength > queue->VirtualDeviceLength))
{
CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
continue;
}
#ifdef TC_TRACE_IO_QUEUE
Dump ("Q %I64d [%I64d] %c len=%d\n", item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), item->Write ? 'W' : 'R', item->OriginalLength);
#endif
if (!queue->IsFilterDevice)
{
// Adjust the offset for host file or device
if (queue->CryptoInfo->hiddenVolume)
item->OriginalOffset.QuadPart += queue->CryptoInfo->hiddenVolumeOffset;
else
item->OriginalOffset.QuadPart += queue->CryptoInfo->volDataAreaOffset;
// Hidden volume protection
if (item->Write && queue->CryptoInfo->bProtectHiddenVolume)
{
// If there has already been a write operation denied in order to protect the
// hidden volume (since the volume mount time)
if (queue->CryptoInfo->bHiddenVolProtectionAction)
{
// Do not allow writing to this volume anymore. This is to fake a complete volume
// or system failure (otherwise certain kinds of inconsistency within the file
// system could indicate that this volume has used hidden volume protection).
CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
continue;
}
// Verify that no byte is going to be written to the hidden volume area
if (RegionsOverlap ((unsigned __int64) item->OriginalOffset.QuadPart,
(unsigned __int64) item->OriginalOffset.QuadPart + item->OriginalLength - 1,
queue->CryptoInfo->hiddenVolumeOffset,
(unsigned __int64) queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1))
{
Dump ("Hidden volume protection triggered: write %I64d-%I64d (protected %I64d-%I64d)\n", item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1);
queue->CryptoInfo->bHiddenVolProtectionAction = TRUE;
// Deny this write operation to prevent the hidden volume from being overwritten
CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
continue;
}
}
}
else if (item->Write && IsHiddenSystemRunning()
&& (RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, SECTOR_SIZE, TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE - 1)
|| RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, GetBootDriveLength(), _I64_MAX)))
{
Dump ("Preventing write to boot loader or host protected area\n");
CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0);
continue;
}
// Original IRP data buffer
mdlWaitTime = 0;
mdlWaitPerfCounter.QuadPart = 0;
while (TRUE)
{
dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority);
if (dataBuffer || mdlWaitTime >= TC_ENC_IO_QUEUE_MEM_ALLOC_TIMEOUT)
break;
if (mdlWaitPerfCounter.QuadPart == 0)
GetElapsedTimeInit (&mdlWaitPerfCounter);
TCSleep (TC_ENC_IO_QUEUE_MEM_ALLOC_RETRY_DELAY);
mdlWaitTime += GetElapsedTime (&mdlWaitPerfCounter) / 1000;
}
if (dataBuffer == NULL)
{
CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
continue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -