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

📄 ntvol.c

📁 一个提供档案及Partition作加解密的程式支援以下的加密演算法AESBlowfishCAST5SerpentTriple DESTwofishAES-BlowfishAES-TwofishAES-
💻 C
📖 第 1 页 / 共 2 页
字号:
/* The source code contained in this file has been derived from the source code
   of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
   additions to that source code contained in this file are Copyright (c) 2004-2005
   TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
   parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
   release. Please see the file license.txt for full license details. */

#include "TCdefs.h"
#include "crypto.h"
#include "volumes.h"

#include "apidrvr.h"
#include "ntdriver.h"
#include "ntvol.h"
#include "ntrawdv.h"
#include "ntfiledv.h"

#include "cache.h"

//#ifdef _DEBUG
//#define EXTRA_INFO 1
//#endif

#pragma warning( disable : 4127 )

NTSTATUS
TCOpenVolume (PDEVICE_OBJECT DeviceObject,
	       PEXTENSION Extension,
	       MOUNT_STRUCT * mount,
	       PWSTR pwszMountVolume,
	       BOOL bRawDevice)
{
	FILE_STANDARD_INFORMATION FileStandardInfo;
	FILE_BASIC_INFORMATION FileBasicInfo;
	OBJECT_ATTRIBUTES oaFileAttributes;
	UNICODE_STRING FullFileName;
	IO_STATUS_BLOCK IoStatusBlock;
	LARGE_INTEGER lDiskLength;
	char *readBuffer = 0;
	char *readBufferHiddenVol = 0;
	NTSTATUS ntStatus = 0;
	BOOL bTimeStampValid = FALSE;

	Extension->pfoDeviceFile = NULL;
	Extension->hDeviceFile = NULL;

	RtlInitUnicodeString (&FullFileName, pwszMountVolume);
	InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE,	NULL, NULL);
	KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);

	// If we are opening a device, query its size first
	if (bRawDevice)
	{
		PARTITION_INFORMATION pi;
		DISK_GEOMETRY dg;

		ntStatus = IoGetDeviceObjectPointer (&FullFileName,
			FILE_READ_DATA,
			&Extension->pfoDeviceFile,
			&Extension->pFsdDevice);

		if (!NT_SUCCESS (ntStatus))
		{
			goto error;
		}

		DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);

		// Query partition size
		ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
			Extension, IOCTL_DISK_GET_PARTITION_INFO,
			(char *) &pi, sizeof (pi));

		if (NT_SUCCESS (ntStatus))
		{
			lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
		}
		else
		{
			// Drive geometry info is used only when IOCTL_DISK_GET_PARTITION_INFO fails
			ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
				Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY,
				(char *) &dg, sizeof (dg));

			if (!NT_SUCCESS (ntStatus))
				goto error;

			lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack *
				dg.TracksPerCylinder * dg.BytesPerSector;
		}
	}

	// Open the volume hosting file/device
	if (!mount->bMountReadOnly)
	{
		ntStatus = ZwCreateFile (&Extension->hDeviceFile,
			GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
			&oaFileAttributes,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL |
			FILE_ATTRIBUTE_SYSTEM,
			mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
			FILE_OPEN,
			FILE_WRITE_THROUGH |
			FILE_NO_INTERMEDIATE_BUFFERING |
			FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,
			0);
	}

	/* 26-4-99 NT for some partitions returns this code, it is really a
	access denied */
	if (ntStatus == 0xc000001b)
	{
		ntStatus = STATUS_ACCESS_DENIED;
	}

	if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
	{
		ntStatus = ZwCreateFile (&Extension->hDeviceFile,
			GENERIC_READ | SYNCHRONIZE,
			&oaFileAttributes,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL |
			FILE_ATTRIBUTE_SYSTEM,
			mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
			FILE_OPEN,
			FILE_WRITE_THROUGH |
			FILE_NO_INTERMEDIATE_BUFFERING |
			FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,
			0);
		Extension->bReadOnly = TRUE;
	}
	else
		Extension->bReadOnly = FALSE;

	/* 26-4-99 NT for some partitions returns this code, it is really a
	access denied */
	if (ntStatus == 0xc000001b)
	{
		/* Partitions which return this code can still be opened with
		FILE_SHARE_READ but this causes NT problems elsewhere in
		particular if you do FILE_SHARE_READ NT will die later if
		anyone even tries to open the partition  (or file for that
		matter...)  */
		ntStatus = STATUS_SHARING_VIOLATION;
	}

	if (!NT_SUCCESS (ntStatus))
	{
		goto error;
	}

	// If we have opened a file, query its size now
	if (bRawDevice == FALSE)
	{
		ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
			&IoStatusBlock,
			&FileBasicInfo,
			sizeof (FileBasicInfo),
			FileBasicInformation);

		if (NT_SUCCESS (ntStatus))
		{
			/* Remember the container timestamp. (Used to reset access/modification file date/time
			of file-hosted containers upon dismount or after unsuccessful mount attempt to preserve
			plausible deniability of hidden volumes.) */
			Extension->fileCreationTime = FileBasicInfo.CreationTime;
			Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
			Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
			Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
			bTimeStampValid = TRUE;

			ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
				&IoStatusBlock,
				&FileStandardInfo,
				sizeof (FileStandardInfo),
				FileStandardInformation);
		}

		if (!NT_SUCCESS (ntStatus))
		{
			Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
				ntStatus);
			goto error;
		}

		lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;

		if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
		{
			Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
			mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
			ntStatus = STATUS_SUCCESS;
			goto error;
		}

		ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
			FILE_ALL_ACCESS,
			*IoFileObjectType,
			KernelMode,
			&Extension->pfoDeviceFile,
			0);

		if (!NT_SUCCESS (ntStatus))
		{
			goto error;
		}

		/* Get the FSD device for the file (probably either NTFS or	FAT) */
		Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);

		DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
	}

	// Check volume size
	if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
	{
		mount->nReturnCode = ERR_VOL_SIZE_WRONG;
		ntStatus = STATUS_SUCCESS;
		goto error;
	}
	
	Extension->DiskLength = lDiskLength.QuadPart;

	// Read normal volume header
	readBuffer = TCalloc (HEADER_SIZE);
	if (readBuffer == NULL)
	{
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
		goto error;
	}

	ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL,
		&IoStatusBlock, readBuffer, HEADER_SIZE, NULL, NULL);

	// Read hidden volume header if needed 
	if (mountingHiddenVolumesAllowed)
	{
		LARGE_INTEGER byteOffset;

		readBufferHiddenVol = TCalloc (HEADER_SIZE);
		if (readBufferHiddenVol == NULL)
		{
			ntStatus = STATUS_INSUFFICIENT_RESOURCES;
			goto error;
		}

		byteOffset.QuadPart = lDiskLength.QuadPart - HIDDEN_VOL_HEADER_OFFSET;
		ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL,
			&IoStatusBlock, readBufferHiddenVol, HEADER_SIZE, &byteOffset, NULL);
	}

	if (!NT_SUCCESS (ntStatus))
	{
		Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
	}
	else if (IoStatusBlock.Information != HEADER_SIZE)
	{
		Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, HEADER_SIZE);
		ntStatus = STATUS_UNSUCCESSFUL;
	}

	if (!NT_SUCCESS (ntStatus))
	{
		goto error;
	}


	/* Attempt to recognize the volume */

	mount->nReturnCode = VolumeReadHeaderCache (
								mount->bCache,
								readBuffer,
								readBufferHiddenVol,
								mount->szPassword,
								strlen (mount->szPassword),
								&Extension->cryptoInfo);

	if (mount->nReturnCode == 0)
	{
		/* Volume header successfully decrypted */

		if (Extension->cryptoInfo->hiddenVolume)
		{
			// Hidden volume setup

			// Validate the size of the hidden volume specified in the header
			if (Extension->DiskLength < (__int64) Extension->cryptoInfo->hiddenVolumeSize + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE
				|| Extension->cryptoInfo->hiddenVolumeSize <= 0)
			{
				mount->nReturnCode = ERR_VOL_SIZE_WRONG;
				ntStatus = STATUS_SUCCESS;
				goto error;
			}

			// Determine the offset of the hidden volume
			Extension->cryptoInfo->hiddenVolumeOffset = Extension->DiskLength - Extension->cryptoInfo->hiddenVolumeSize - HIDDEN_VOL_HEADER_OFFSET;

			Dump("Hidden volume offset = %I64d", Extension->cryptoInfo->hiddenVolumeOffset);

			// Validate the offset
			if (Extension->cryptoInfo->hiddenVolumeOffset % SECTOR_SIZE != 0)
			{
				mount->nReturnCode = ERR_VOL_SIZE_WRONG;
				ntStatus = STATUS_SUCCESS;
				goto error;
			}

			// Set volume size
			Extension->DiskLength = Extension->cryptoInfo->hiddenVolumeSize;	
		}
		else
		{
			// Normal (not a hidden) volume

			// Set volume size
			Extension->DiskLength -= HEADER_SIZE;
		}

		// Calculate virtual volume geometry
		Extension->TracksPerCylinder = 1;
		Extension->SectorsPerTrack = 1;
		Extension->BytesPerSector = 512;
		Extension->NumberOfCylinders = Extension->DiskLength / 512;
		Extension->PartitionType = 0;

		Extension->bRawDevice = bRawDevice;

		if (wcslen (pwszMountVolume) < 64)
			wcscpy (Extension->wszVolume, pwszMountVolume);
		else
		{
			memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2);
			Extension->wszVolume[60] = (WCHAR) '.';
			Extension->wszVolume[61] = (WCHAR) '.';
			Extension->wszVolume[62] = (WCHAR) '.';
			Extension->wszVolume[63] = (WCHAR) 0;
		}

		Extension->mountTime = mount->time;

		TCfree (readBuffer);
		return STATUS_SUCCESS;
	}


	/* Failed due to some non-OS reason so we drop through and return NT
	   SUCCESS then nReturnCode is checked later in user-mode */

	if (mount->nReturnCode == ERR_OUTOFMEMORY)
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
	else
		ntStatus = STATUS_SUCCESS;

error:

	if (bTimeStampValid)
	{
		/* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
		RestoreTimeStamp (Extension);
		bTimeStampValid = FALSE;
	}

	/* Close the hDeviceFile */
	if (Extension->hDeviceFile != NULL)
		ZwClose (Extension->hDeviceFile);

	/* The cryptoInfo pointer is deallocated if the readheader routines
	   fail so there is no need to deallocate here  */

	/* Dereference the user-mode file object */
	if (Extension->pfoDeviceFile != NULL)
		ObDereferenceObject (Extension->pfoDeviceFile);

	/* Free the tmp IO buffers */
	if (readBuffer != NULL)
		TCfree (readBuffer);

	if (readBufferHiddenVol != NULL)
		TCfree (readBufferHiddenVol);

	return ntStatus;
}

void
TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
{
	if (DeviceObject);	/* Remove compiler warning */

	if (Extension->hDeviceFile != NULL)
	{
		if (Extension->bRawDevice == FALSE)
		{
			/* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
			RestoreTimeStamp (Extension);
		}

		ZwClose (Extension->hDeviceFile);
	}
	ObDereferenceObject (Extension->pfoDeviceFile);
	crypto_close (Extension->cryptoInfo);
}

/* This rountine can be called at any IRQL so we need to tread carefully. Not
   even DbgPrint or KdPrint are called here as the kernel sometimes faults if
   they are called at high IRQL */

NTSTATUS
TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer)
{
	PIO_STACK_LOCATION irpSp;
	PEXTENSION Extension;
	NTSTATUS ntStatus;

	Extension = (PEXTENSION) DeviceObject->DeviceExtension;

	/* Check to make sure the DeviceObject passed in is actually ours! */
	if (Extension->lMagicNumber != 0xabfeacde)
		KeBugCheck ((ULONG) 0xabfeacde);

	ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19);

#ifdef USE_KERNEL_MUTEX
	KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode,
			      FALSE, NULL);
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -