⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drivefilter.c

📁 功能强大的开源加密软件。使用最新ieee-p1619标准
💻 C
📖 第 1 页 / 共 3 页
字号:
}


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 + -