📄 bootencryption.cpp
字号:
// Convert absolute path to relative to the Windows directory
driverPath = pathBuf;
driverPath = driverPath.substr (driverPath.rfind ("\\", driverPath.rfind ("\\", driverPath.rfind ("\\") - 1) - 1) + 1);
if (Is64BitOs())
driverPath = "SysWOW64" + driverPath.substr (driverPath.find ("\\"));
}
}
throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL,
driverPath.empty() ? NULL : driverPath.c_str(),
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);
}
void BootEncryption::InvalidateCachedSysDriveProperties ()
{
DriveConfigValid = false;
RealSystemDriveSizeValid = false;
}
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];
throw_sys_if (GetSystemDirectory (buf, sizeof (buf)) == 0);
return string (buf);
}
string BootEncryption::GetTempPath ()
{
char tempPath[MAX_PATH];
DWORD tempLen = ::GetTempPath (sizeof (tempPath), tempPath);
if (tempLen == 0 || tempLen > sizeof (tempPath))
throw ParameterIncorrect (SRC_POS);
return string (tempPath);
}
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;
}
}
BootEncryptionStatus BootEncryption::GetStatus ()
{
/* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
BootEncryptionStatus status;
CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status));
return status;
}
void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties)
{
if (properties == NULL)
throw ParameterIncorrect (SRC_POS);
CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties));
}
bool BootEncryption::IsHiddenSystemRunning ()
{
int hiddenSystemStatus;
CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus));
return hiddenSystemStatus != 0;
}
bool BootEncryption::SystemDriveContainsPartitionType (byte type)
{
Device device (GetSystemDriveConfiguration().DevicePath, true);
byte mbrBuf[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbrBuf, sizeof (mbrBuf));
MBR *mbr = reinterpret_cast <MBR *> (mbrBuf);
if (mbr->Signature != 0xaa55)
throw ParameterIncorrect (SRC_POS);
for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i)
{
if (mbr->Partitions[i].Type == type)
return true;
}
return false;
}
bool BootEncryption::SystemDriveContainsExtendedPartition ()
{
return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED);
}
bool BootEncryption::SystemDriveIsDynamic ()
{
GetSystemDriveConfigurationRequest request;
_snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str());
CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
return request.DriveIsDynamic ? true : false;
}
SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration ()
{
if (DriveConfigValid)
return DriveConfig;
SystemDriveConfiguration config;
string winDir = GetWindowsDirectory();
// Scan all drives
for (int driveNumber = 0; driveNumber < 32; ++driveNumber)
{
bool windowsFound = false;
config.SystemLoaderPresent = false;
PartitionList partitions = GetDrivePartitions (driveNumber);
foreach (const Partition &part, partitions)
{
if (!part.MountPoint.empty()
&& (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0))
{
config.SystemLoaderPresent = true;
}
if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0)
{
config.SystemPartition = part;
windowsFound = true;
}
}
if (windowsFound)
{
config.DriveNumber = driveNumber;
stringstream ss;
ss << "PhysicalDrive" << driveNumber;
config.DevicePath = ss.str();
stringstream kernelPath;
kernelPath << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
config.DeviceKernelPath = kernelPath.str();
config.DrivePartition = partitions.front();
partitions.pop_front();
config.Partitions = partitions;
config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull;
config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart;
foreach (const Partition &part, config.Partitions)
{
if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace)
config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart;
config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart;
}
DriveConfig = config;
DriveConfigValid = true;
return DriveConfig;
}
}
throw ParameterIncorrect (SRC_POS);
}
bool BootEncryption::SystemPartitionCoversWholeDrive ()
{
SystemDriveConfiguration config = GetSystemDriveConfiguration();
return config.Partitions.size() == 1
&& config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB;
}
uint32 BootEncryption::GetChecksum (byte *data, size_t size)
{
uint32 sum = 0;
while (size-- > 0)
{
sum += *data++;
sum = _rotl (sum, 1);
}
return sum;
}
void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation)
{
if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE)
throw ParameterIncorrect (SRC_POS);
ZeroMemory (buffer, bufferSize);
int ea = 0;
if (GetStatus().DriveMounted)
{
try
{
GetBootEncryptionAlgorithmNameRequest request;
CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request));
if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0)
ea = AES;
else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
ea = SERPENT;
else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
ea = TWOFISH;
}
catch (...)
{
try
{
VOLUME_PROPERTIES_STRUCT properties;
GetVolumeProperties (&properties);
ea = properties.ea;
}
catch (...) { }
}
}
else
{
if (SelectedEncryptionAlgorithmId == 0)
throw ParameterIncorrect (SRC_POS);
ea = SelectedEncryptionAlgorithmId;
}
int bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR;
int bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER;
switch (ea)
{
case AES:
bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES;
bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES;
break;
case SERPENT:
bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT;
bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT;
break;
case TWOFISH:
bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH;
bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH;
break;
}
// Boot sector
DWORD size;
byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size);
if (!bootSecResourceImg || size != SECTOR_SIZE)
throw ParameterIncorrect (SRC_POS);
memcpy (buffer, bootSecResourceImg, size);
*(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM);
if (nCurrentOS == WIN_VISTA_OR_LATER)
buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
// Checksum of the backup header of the outer volume for the hidden system
if (hiddenOSCreation)
{
Device device (GetSystemDriveConfiguration().DevicePath);
byte headerSector[SECTOR_SIZE];
device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE);
device.Read (headerSector, sizeof (headerSector));
*(uint16 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = (uint16) GetCrc32 (headerSector, sizeof (headerSector));
}
// Decompressor
byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size);
if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE)
throw ParameterIncorrect (SRC_POS);
memcpy (buffer + SECTOR_SIZE, decompressor, size);
// Compressed boot loader
byte *bootLoader = MapResource ("BIN", bootLoaderId, &size);
if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE)
throw ParameterIncorrect (SRC_POS);
memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size);
// Boot loader and decompressor checksum
*(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast <uint16> (size);
*(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE,
TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size);
// Backup of decompressor and boot loader
if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE)
{
memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE,
buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE);
buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE;
}
else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER)
{
throw ParameterIncorrect (SRC_POS);
}
}
void BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage)
{
if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE)
throw ParameterIncorrect (SRC_POS);
GetSystemDriveConfigurationRequest request;
_snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str());
try
{
CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
if (config)
*config = request.Configuration;
if (userConfig)
*userConfig = request.UserConfiguration;
if (customUserMessage)
{
request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0;
*customUserMessage = request.CustomUserMessage;
}
}
catch (...)
{
if (config)
*config = 0;
if (userConfig)
*userConfig = 0;
if (customUserMessage)
customUserMessage->clear();
}
}
void BootEncryption::WriteBootSectorConfig (const byte newConfig[])
{
Device device (GetSystemDriveConfiguration().DevicePath);
byte mbr[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbr, sizeof (mbr));
memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE);
device.SeekAt (0);
device.Write (mbr, sizeof (mbr));
byte mbrVerificationBuf[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbrVerificationBuf, sizeof (mbr));
if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
throw ErrorException ("ERROR_MBR_PROTECTED");
}
void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage)
{
Device device (GetSystemDriveConfiguration().DevicePath);
byte mbr[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbr, sizeof (mbr));
mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig;
memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
if (!customUserMessage.empty())
{
if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)
throw ParameterIncorrect (SRC_POS);
memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -