📄 bootencryption.cpp
字号:
/*
Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
Governed by the TrueCrypt License 2.4 the full text of which is contained
in the file License.txt included in TrueCrypt binary and source code
distribution packages.
*/
#include "Tcdefs.h"
#include "Platform/Finally.h"
#include "Platform/ForEach.h"
#include <Setupapi.h>
#include <devguid.h>
#include <io.h>
#include <shlobj.h>
#include <atlbase.h>
#include "BootEncryption.h"
#include "Boot/Windows/BootCommon.h"
#include "Common/Resource.h"
#include "Crc.h"
#include "Crypto.h"
#include "Dlgcode.h"
#include "Endian.h"
#include "Random.h"
#include "Registry.h"
#include "Volumes.h"
#ifdef VOLFORMAT
#include "Format/FormatCom.h"
#elif defined (TCMOUNT)
#include "Mount/MainCom.h"
#endif
namespace TrueCrypt
{
#if !defined (SETUP)
class Elevator
{
public:
static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
{
Elevate();
CComBSTR inputBstr;
if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK)
throw ParameterIncorrect (SRC_POS);
CComBSTR outputBstr;
if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK)
throw ParameterIncorrect (SRC_POS);
DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr);
if (result != ERROR_SUCCESS)
{
SetLastError (result);
throw SystemException();
}
}
static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone)
{
Elevate();
CComBSTR bufferBstr;
if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK)
throw ParameterIncorrect (SRC_POS);
DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone);
if (result != ERROR_SUCCESS)
{
SetLastError (result);
throw SystemException();
}
if (!write)
memcpy (buffer, (BYTE *) bufferBstr.m_str, size);
}
static void RegisterFilterDriver (bool registerDriver)
{
Elevate();
DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE);
if (result != ERROR_SUCCESS)
{
SetLastError (result);
throw SystemException();
}
}
static void Release ()
{
if (ElevatedComInstance)
{
ElevatedComInstance->Release();
ElevatedComInstance = nullptr;
CoUninitialize ();
}
}
static void SetDriverServiceStartType (DWORD startType)
{
Elevate();
DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType);
if (result != ERROR_SUCCESS)
{
SetLastError (result);
throw SystemException();
}
}
protected:
static void Elevate ()
{
if (IsAdmin())
{
SetLastError (ERROR_ACCESS_DENIED);
throw SystemException();
}
if (!ElevatedComInstance)
{
CoInitialize (NULL);
ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg);
}
}
#if defined (TCMOUNT)
static ITrueCryptMainCom *ElevatedComInstance;
#elif defined (VOLFORMAT)
static ITrueCryptFormatCom *ElevatedComInstance;
#endif
};
#if defined (TCMOUNT)
ITrueCryptMainCom *Elevator::ElevatedComInstance;
#elif defined (VOLFORMAT)
ITrueCryptFormatCom *Elevator::ElevatedComInstance;
#endif
#else // SETUP
class Elevator
{
public:
static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); }
static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); }
static void RegisterFilterDriver (bool registerDriver) { throw ParameterIncorrect (SRC_POS); }
static void Release () { }
static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); }
};
#endif // SETUP
File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false)
{
Handle = CreateFile (path.c_str(),
readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
try
{
throw_sys_if (Handle == INVALID_HANDLE_VALUE);
}
catch (SystemException &)
{
if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
Elevated = true;
else
throw;
}
FileOpen = true;
FilePointerPosition = 0;
IsDevice = false;
Path = path;
}
void File::Close ()
{
if (FileOpen)
{
if (!Elevated)
CloseHandle (Handle);
FileOpen = false;
}
}
DWORD File::Read (byte *buffer, DWORD size)
{
DWORD bytesRead;
if (Elevated)
{
DWORD bytesRead;
Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead);
FilePointerPosition += bytesRead;
return bytesRead;
}
throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL));
return bytesRead;
}
void File::SeekAt (int64 position)
{
if (Elevated)
{
FilePointerPosition = position;
}
else
{
LARGE_INTEGER pos;
pos.QuadPart = position;
throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN));
}
}
void File::Write (byte *buffer, DWORD size)
{
DWORD bytesWritten;
if (Elevated)
{
Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten);
FilePointerPosition += bytesWritten;
throw_sys_if (bytesWritten != size);
}
else
{
throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size);
}
}
void Show (HWND parent, const string &str)
{
MessageBox (parent, str.c_str(), NULL, 0);
}
Device::Device (string path, bool readOnly)
{
FileOpen = false;
Elevated = false;
Handle = CreateFile ((string ("\\\\.\\") + path).c_str(),
readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
try
{
throw_sys_if (Handle == INVALID_HANDLE_VALUE);
}
catch (SystemException &)
{
if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
Elevated = true;
else
throw;
}
FileOpen = true;
FilePointerPosition = 0;
IsDevice = true;
Path = path;
}
BootEncryption::~BootEncryption ()
{
if (RescueIsoImage)
delete RescueIsoImage;
Elevator::Release();
}
void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
{
try
{
DWORD bytesReturned;
throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL));
}
catch (SystemException &)
{
if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
Elevator::CallDriver (ioctl, input, inputSize, output, outputSize);
else
throw;
}
}
DWORD BootEncryption::GetDriverServiceStartType ()
{
DWORD startType;
throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType));
return startType;
}
void BootEncryption::SetDriverServiceStartType (DWORD startType)
{
if (!IsAdmin() && IsUacSupported())
{
Elevator::SetDriverServiceStartType (startType);
return;
}
BOOL startOnBoot = (startType == SERVICE_BOOT_START);
SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
throw_sys_if (!serviceManager);
finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); });
SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG);
throw_sys_if (!service);
finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); });
throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, NULL,
startOnBoot ? "Filter" : NULL,
NULL, NULL, NULL, NULL, NULL));
// ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER
throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType));
}
void BootEncryption::ProbeRealSystemDriveSize ()
{
if (RealSystemDriveSizeValid)
return;
GetSystemDriveConfiguration();
ProbeRealDriveSizeRequest request;
_snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str());
CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request));
DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize;
RealSystemDriveSizeValid = TRUE;
if (request.TimeOut)
throw TimeOut (SRC_POS);
}
PartitionList BootEncryption::GetDrivePartitions (int driveNumber)
{
PartitionList partList;
for (int partNumber = 0; partNumber < 64; ++partNumber)
{
stringstream partPath;
partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber;
DISK_PARTITION_INFO_STRUCT diskPartInfo;
_snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str());
try
{
CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo));
}
catch (...)
{
continue;
}
Partition part;
part.DevicePath = partPath.str();
part.Number = partNumber;
part.Info = diskPartInfo.partInfo;
part.IsGPT = diskPartInfo.IsGPT;
// Mount point
wstringstream ws;
ws << partPath.str().c_str();
int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str());
if (driveNumber >= 0)
{
part.MountPoint += (char) (driveNumber + 'A');
part.MountPoint += ":";
}
partList.push_back (part);
}
return partList;
}
DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber)
{
stringstream devName;
devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
DISK_GEOMETRY geometry;
throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry));
return geometry;
}
string BootEncryption::GetWindowsDirectory ()
{
char buf[MAX_PATH];
if (GetSystemDirectory (buf, sizeof (buf)) > 0)
return string (buf);
return string();
}
uint16 BootEncryption::GetInstalledBootLoaderVersion ()
{
uint16 version;
CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version));
return version;
}
// Note that this does not require admin rights (it just requires the driver to be running)
bool BootEncryption::IsBootLoaderOnDrive (char *devicePath)
{
try
{
OPEN_TEST_STRUCT openTestStruct;
DWORD dwResult;
strcpy ((char *) &openTestStruct.wszFileName[0], devicePath);
ToUNICODE ((char *) &openTestStruct.wszFileName[0]);
openTestStruct.bDetectTCBootLoader = TRUE;
return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
&openTestStruct, sizeof (OPEN_TEST_STRUCT),
NULL, 0,
&dwResult, NULL) == TRUE);
}
catch (...)
{
return false;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -