Автоматизируйте TrueCrypt, используя его драйвер вместо командной строки
Если я хочу увидеть все тома, смонтированные с помощью C#, мне придется запросить настоящий драйвер шифрования, потому что нет команды, которую я могу отправить TrueCrypt.exe, которая вернет мне эту информацию.
Поэтому, если я хочу увидеть все тома, которые смонтированы, и на том диске, на котором они смонтированы, я назову TrueCryptHelper.GetMountedVolumes();
:
вот код:
public static class TrueCryptHelper
{
public static Dictionary<char, string> GetMountedVolumes()
{
uint size = (uint)Marshal.SizeOf(typeof(MOUNT_LIST_STRUCT));
IntPtr buffer = Marshal.AllocHGlobal((int)size);
uint bytesReturned;
IntPtr _hdev = CreateFile("\\\\.\\TrueCrypt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
bool bResult = DeviceIoControl(_hdev, TC_GET_MOUNTED_VOLUMES, buffer, size, buffer, size, out bytesReturned, IntPtr.Zero);
MOUNT_LIST_STRUCT mount = new MOUNT_LIST_STRUCT();
Marshal.PtrToStructure(buffer, mount);
Marshal.FreeHGlobal(buffer);
Dictionary<char, string> items = new Dictionary<char, string>();
for (int i = 0; i < 26; i++)
{
string filePath = mount.wszVolume[i].ToString().Replace(@"\??\", "");
if (filePath.Length > 2)
{
items[(char)('A' + i)] = filePath;
}
//Console.WriteLine("{0}: => {1}", (char)('A' + i), mount.wszVolume[i]);
}
return items;
}
private static readonly uint TC_GET_DRIVER_VERSION = (uint)CTL_CODE(0x00000022, 0x800 + (01), 0, 0);
private static readonly uint TC_GET_BOOT_LOADER_VERSION = (uint)CTL_CODE(0x00000022, 0x800 + (02), 0, 0);
private static readonly uint TC_MOUNT_VOLUME = (uint)CTL_CODE(0x00000022, 0x800 + (03), 0, 0);
private static readonly uint TC_DISMOUNT_VOLUME = (uint)CTL_CODE(0x00000022, 0x800 + (04), 0, 0);
private static readonly uint TC_DISMOUNT_ALL_VOLUMES = (uint)CTL_CODE(0x00000022, 0x800 + (05), 0, 0);
private static readonly uint TC_GET_MOUNTED_VOLUMES = (uint)CTL_CODE(0x00000022, 0x800 + (06), 0, 0);
private static readonly uint TC_GET_VOLUME_PROPERTIES = (uint)CTL_CODE(0x00000022, 0x800 + (07), 0, 0);
private static readonly uint TC_GET_DEVICE_REFCOUNT = (uint)CTL_CODE(0x00000022, 0x800 + (08), 0, 0);
private static readonly uint TC_WAS_REFERENCED_DEVICE_DELETED = (uint)CTL_CODE(0x00000022, 0x800 + (09), 0, 0);
private static readonly uint TC_IS_ANY_VOLUME_MOUNTED = (uint)CTL_CODE(0x00000022, 0x800 + (10), 0, 0);
private static readonly uint TC_GET_PASSWORD_CACHE_STATUS = (uint)CTL_CODE(0x00000022, 0x800 + (11), 0, 0);
private static readonly uint TC_WIPE_PASSWORD_CACHE = (uint)CTL_CODE(0x00000022, 0x800 + (12), 0, 0);
private static readonly uint TC_OPEN_TEST = (uint)CTL_CODE(0x00000022, 0x800 + (13), 0, 0);
private static readonly uint TC_GET_DRIVE_PARTITION_INFO = (uint)CTL_CODE(0x00000022, 0x800 + (14), 0, 0);
private static readonly uint TC_GET_DRIVE_GEOMETRY = (uint)CTL_CODE(0x00000022, 0x800 + (15), 0, 0);
private static readonly uint TC_PROBE_REAL_DRIVE_SIZE = (uint)CTL_CODE(0x00000022, 0x800 + (16), 0, 0);
private static readonly uint TC_GET_RESOLVED_SYMLINK = (uint)CTL_CODE(0x00000022, 0x800 + (17), 0, 0);
private static readonly uint TC_GET_BOOT_ENCRYPTION_STATUS = (uint)CTL_CODE(0x00000022, 0x800 + (18), 0, 0);
private static readonly uint TC_BOOT_ENCRYPTION_SETUP = (uint)CTL_CODE(0x00000022, 0x800 + (19), 0, 0);
private static readonly uint TC_ABORT_BOOT_ENCRYPTION_SETUP = (uint)CTL_CODE(0x00000022, 0x800 + (20), 0, 0);
private static readonly uint TC_GET_BOOT_ENCRYPTION_SETUP_RESULT = (uint)CTL_CODE(0x00000022, 0x800 + (21), 0, 0);
private static readonly uint TC_GET_BOOT_DRIVE_VOLUME_PROPERTIES = (uint)CTL_CODE(0x00000022, 0x800 + (22), 0, 0);
private static readonly uint TC_REOPEN_BOOT_VOLUME_HEADER = (uint)CTL_CODE(0x00000022, 0x800 + (23), 0, 0);
private static readonly uint TC_GET_BOOT_ENCRYPTION_ALGORITHM_NAME = (uint)CTL_CODE(0x00000022, 0x800 + (24), 0, 0);
private static readonly uint TC_GET_PORTABLE_MODE_STATUS = (uint)CTL_CODE(0x00000022, 0x800 + (25), 0, 0);
private static readonly uint TC_SET_PORTABLE_MODE_STATUS = (uint)CTL_CODE(0x00000022, 0x800 + (26), 0, 0);
private static readonly uint TC_IS_HIDDEN_SYSTEM_RUNNING = (uint)CTL_CODE(0x00000022, 0x800 + (27), 0, 0);
private static readonly uint TC_GET_SYSTEM_DRIVE_CONFIG = (uint)CTL_CODE(0x00000022, 0x800 + (28), 0, 0);
private static readonly uint TC_DISK_IS_WRITABLE = (uint)CTL_CODE(0x00000022, 0x800 + (29), 0, 0);
private static readonly uint TC_START_DECOY_SYSTEM_WIPE = (uint)CTL_CODE(0x00000022, 0x800 + (30), 0, 0);
private static readonly uint TC_ABORT_DECOY_SYSTEM_WIPE = (uint)CTL_CODE(0x00000022, 0x800 + (31), 0, 0);
private static readonly uint TC_GET_DECOY_SYSTEM_WIPE_STATUS = (uint)CTL_CODE(0x00000022, 0x800 + (32), 0, 0);
private static readonly uint TC_GET_DECOY_SYSTEM_WIPE_RESULT = (uint)CTL_CODE(0x00000022, 0x800 + (33), 0, 0);
private static readonly uint TC_WRITE_BOOT_DRIVE_SECTOR = (uint)CTL_CODE(0x00000022, 0x800 + (34), 0, 0);
private static readonly uint TC_IS_SYSTEM_FAVORITE_VOLUME_DIRTY = (uint)CTL_CODE(0x00000022, 0x800 + (35), 0, 0);
private static readonly uint TC_SET_SYSTEM_FAVORITE_VOLUME_DIRTY = (uint)CTL_CODE(0x00000022, 0x800 + (36), 0, 0);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
private class MOUNT_LIST_STRUCT
{
public readonly UInt32 ulMountedDrives; /* Bitfield of all mounted drive letters */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
public readonly MOUNT_LIST_STRUCT_VOLUME_NAME[] wszVolume; /* Volume names of mounted volumes */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
public readonly UInt64[] diskLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
public readonly int[] ea;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
public readonly int[] volumeType; /* Volume type (e.g. PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
private struct MOUNT_LIST_STRUCT_VOLUME_NAME
{
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 260)]
public readonly char[] wszVolume; /* Volume names of mounted volumes */
public override string ToString()
{
return (new String(wszVolume)).TrimEnd('\0');
}
}
private static int CTL_CODE(int DeviceType, int Function, int Method, int Access)
{
return (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2)
| (Method));
}
/// <summary>
/// Sends a control code directly to a specified device driver, causing the corresponding device to perform the corresponding operation.
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
/// </summary>
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
IntPtr lpInBuffer, uint nInBufferSize,
IntPtr lpOutBuffer, uint nOutBufferSize,
out uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
[MarshalAs(UnmanagedType.U4)] FileAccess access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
IntPtr templateFile);
}
Обратите внимание, я использую TC_GET_MOUNTED_VOLUMES
флаг. Например, если я хочу смонтировать том и использовать TC_MOUNT_VOLUME
как я укажу пароль? Где я могу найти больше информации о том, как использовать TrueCrypt Driver? Итак, я нашел эту замечательную статью: http://stoned-vienna.com/html/index.php?page=abusing-the-truecrypt-driver
2 ответа
На самом деле это что-то немного продвинутое, это не просто, вам нужно пройти через код C++, понять его и переписать его на C#. Я могу помочь вам с монтированием кода, но для других функций вам необходимо понять, как интерфейс Truecrypt взаимодействует с драйвером ядра, и переписать его на C#.
Про монтаж...
1) Загрузите исходный код последней версии Truecrypt для Windows.
2) Найдите TrueCryptSource\Common\Dlgcode.c Перейдите к строке: 5963, и вы увидите функцию MountVolume:
// Use only cached passwords if password = NULL
//
// Returns:
// -1 = user aborted mount / error
// 0 = mount failed
// 1 = mount OK
// 2 = mount OK in shared mode
//
// Note that some code calling this relies on the content of the mountOptions struct
// to remain unmodified (don't remove the 'const' without proper revision).
int MountVolume (HWND hwndDlg,
int driveNo,
char *volumePath,
Password *password,
BOOL cachePassword,
BOOL sharedAccess,
const MountOptions* const mountOptions,
BOOL quiet,
BOOL bReportWrongPassword)
Хорошо, как вы можете видеть, эта функция получает несколько параметров и отправляет их драйверу ядра, но изменяет некоторую переменную перед передачей их ядру, например, когда вы вводите volumepath
, если в нем есть "\?\", функция удаляет его перед передачей строки драйверу.
Для пути диска, он использует VolumeGuidPathToDevicePath
чтобы получить полный путь к устройству на этом диске (то есть преобразование G: H: I: в полный путь к устройству, например, \Device\Harddisk%d\Partition%d)
Затем есть структура монтирования, вам нужно восстановить ее в C#:
MOUNT_STRUCT mount;
typedef struct
{
int nReturnCode; /* Return code back from driver */
BOOL FilesystemDirty;
BOOL VolumeMountedReadOnlyAfterAccessDenied;
BOOL VolumeMountedReadOnlyAfterDeviceWriteProtected;
wchar_t wszVolume[TC_MAX_PATH]; /* Volume to be mounted */
Password VolumePassword; /* User password */
BOOL bCache; /* Cache passwords in driver */
int nDosDriveNo; /* Drive number to mount */
uint32 BytesPerSector;
BOOL bMountReadOnly; /* Mount volume in read-only mode */
BOOL bMountRemovable; /* Mount volume as removable media */
BOOL bExclusiveAccess; /* Open host file/device in exclusive access mode */
BOOL bMountManager; /* Announce volume to mount manager */
BOOL bPreserveTimestamp; /* Preserve file container timestamp */
BOOL bPartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */
int nPartitionInInactiveSysEncScopeDriveNo; /* If bPartitionInInactiveSysEncScope is TRUE, this contains the drive number of the system drive on which the partition is located. */
BOOL SystemFavorite;
// Hidden volume protection
BOOL bProtectHiddenVolume; /* TRUE if the user wants the hidden volume within this volume to be protected against being overwritten (damaged) */
Password ProtectedHidVolPassword; /* Password to the hidden volume to be protected against overwriting */
BOOL UseBackupHeader;
BOOL RecoveryMode;
} MOUNT_STRUCT;
Вам нужно переписать его в C#, затем инициализировать новый экземпляр этой структуры, затем установить все параметры, необходимые для монтирования тома (пароль, файлы ключей и т. Д.)
Наконец позвоните водителю с MOUNT_STRUCT
экземпляр, который вы создали:
bResult = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, &mount,
sizeof (mount), &mount, sizeof (mount), &dwResult, NULL);
Это все, также как TrueCrypt
делает это, не забудьте стереть пароль из памяти после отправки его в ядро, для этого, TrueCrypt
иметь функцию под названием burn
перепишите его в C# или просто уничтожьте переменные, содержащие пароль для тома, так как он слишком чувствителен.
В дополнение ко всему, что я сказал выше, truecrypt имеет интерфейс командной строки, и вы можете подключать тома из командной строки. Вы не можете использовать командную строку для просмотра списка подключенных дисков, поэтому вам нужен простой код C# для просмотра списка подключенных томов, но вы можете использовать командную строку для подключения:
truecrypt /v myvolume.tc /lx /a /p MyPassword /e /b
Изменить для ясности:
Управляемый драйвер TrueCrypt представляет собой переписывание частей исходного кода TrueCrypt с использованием концепций Managed .NET поверх существующего драйвера TrueCrypt.sys.
Использовать:
Public Sub Main()
' Instantiate the TrueCrypt Driver API
Dim Driver As New TC_Driver("C:\truecrypt.sys") ' Or wherever the compiled TrueCrypt driver exists on your system
End Sub
Это вызывает внутренний код:
Public Class TC_Driver
Implements IDisposable
Const CURRENT_VER As Integer = &H71A
Private pDriver32bitLocation As String
Private pDriver64bitLocation As String
Private pIsPortableMode As Boolean = False
Private Property ManagedDriver As ManagedDriver
Private DriverSetupMutex As Mutex
Public Sub New(ByVal DriverLocation64bit As String)
'Checks for 64-bit OS. Currently x64 is the only supported platform
If Not Environment.Is64BitProcess = Environment.Is64BitOperatingSystem Then
Throw New PlatformNotSupportedException("TrueCryptAPI needs a 64 bit process to run correctly")
End If
' Set the driver location as specified by DriverLocation64bit
pDriver64bitLocation = Path.GetFullPath(DriverLocation64bit)
Dim DriverStatus As TC_ERROR
Dim DriverLoadAttempts As Integer = 0
'Load the driver as a service using internal code
ManagedDriver = New ManagedDriver
'Attempt to Start the driver, fail with error after 3 attempts
Do
DriverStatus = StartDriver()
DriverLoadAttempts += 1
Loop While DriverStatus = TC_ERROR.FILES_OPEN_LOCK AndAlso DriverLoadAttempts < 3
If DriverStatus <> TC_ERROR.SUCCESS Then
Me.Dispose()
Throw New ArgumentException("Driver not loaded. Error:" & DriverStatus)
End If
End Sub
'....
End Class
Приведенный выше код создает экземпляр драйвера TrueCrypt, работающего в качестве службы, и предоставляет объект, для которого можно запускать методы TrueCrypt из вызывающего кода (например, Mount и DisMount).
Чтобы использовать (con't):
Public Sub Main()
' Instantiate the TrueCrypt Driver API
Dim Driver As New TC_Driver("C:\truecrypt.sys") ' Or wherever the compiled TrueCrypt driver exists on your system
Dim MyOptions As New MOUNT_OPTIONS With {.Removable = True}
Driver.MountContainer("C:\MyTrueCryptContainer","S","SuperSecurePassword",MyOptions)
End Sub
Структура MOUNT_OPTIONS:
Public Structure MOUNT_OPTIONS
Dim [ReadOnly] As Boolean
Dim Removable As Boolean
Dim ProtectHiddenVolume As Boolean
Dim PreserveTimestamp As Boolean
Dim PartitionInInactiveSysEncScope As Boolean
Dim ProtectedHidVolPassword As Password
Dim UseBackupHeader As Boolean
Dim RecoveryMode As Boolean
End Structure
Метод MountContainer:
Public Function MountContainer(ByVal FileName As String, ByVal DriveLetter As Char, ByVal Password As Password, ByVal Options As MOUNT_OPTIONS) As TC_ERROR
Dim status As Boolean = False
Dim mounted As TC_ERROR
Dim tmp As String = ""
'Apply the keyfile to the password
If Not Password.ApplyKeyFile(tmp) Then Return False
'Attempt to mount the volume using translated TrueCrypt methods
mounted = MountVolume(Asc(DriveLetter) - Asc("A"), FileName, tmp, False, False, Options, False)
tmp = ""
Options.ProtectedHidVolPassword = Nothing
Return mounted
End Function
Вот (довольно буквальный и громоздкий) перевод C/C++ из TrueCrypt, используемый для монтирования тома:
Partial Public Class TC_Driver
Friend Function MountVolume(ByVal driveNo As Integer, ByVal volumePath As String, ByVal password As String, ByVal cachePassword As Boolean, ByVal sharedAccess As Boolean, ByRef MountOption As MOUNT_OPTIONS, ByVal quiet As Boolean) As TC_ERROR
Dim mount As MOUNT_STRUCT
Dim dwResult As UInteger
Dim bResult As Boolean, bDevice As Boolean
Dim favoriteMountOnArrivalRetryCount As Integer = 0
If IsMountedVolume(volumePath) Then Return TC_ERROR.VOL_ALREADY_MOUNTED
If Not VolumePathExists(volumePath) Then Return TC_ERROR.FILES_OPEN
mount = New MOUNT_STRUCT
mount.VolumePassword = New PASSWORD_STUCT
mount.ProtectedHidVolPassword = New PASSWORD_STUCT
mount.bExclusiveAccess = Not sharedAccess
mount.SystemFavorite = False
mount.UseBackupHeader = MountOption.UseBackupHeader
mount.RecoveryMode = MountOption.RecoveryMode
retry:
mount.nDosDriveNo = driveNo
mount.bCache = cachePassword
mount.bPartitionInInactiveSysEncScope = False
If StringLen(password) > 0 Then
mount.VolumePassword = New PASSWORD_STUCT
mount.VolumePassword.Text = password.PadRight(MAX_PASSWORD + 1, Chr(0))
mount.VolumePassword.Length = StringLen(password)
mount.VolumePassword.Pad = "".PadRight(3, Chr(0))
Else
mount.VolumePassword = New PASSWORD_STUCT
mount.VolumePassword.Text = "".PadRight(MAX_PASSWORD + 1, Chr(0))
mount.VolumePassword.Length = 0
mount.VolumePassword.Pad = "".PadRight(3, Chr(0))
End If
If (Not MountOption.ReadOnly) And MountOption.ProtectHiddenVolume Then
mount.ProtectedHidVolPassword = New PASSWORD_STUCT
mount.ProtectedHidVolPassword.Pad = "".PadRight(3, Chr(0))
MountOption.ProtectedHidVolPassword.ApplyKeyFile(mount.ProtectedHidVolPassword.Text)
mount.ProtectedHidVolPassword.Length = StringLen(mount.ProtectedHidVolPassword.Text)
mount.bProtectHiddenVolume = True
Else
mount.ProtectedHidVolPassword = New PASSWORD_STUCT
mount.ProtectedHidVolPassword.Length = 0
mount.ProtectedHidVolPassword.Text = "".PadRight(MAX_PASSWORD + 1, Chr(0))
mount.ProtectedHidVolPassword.Pad = "".PadRight(3, Chr(0))
mount.bProtectHiddenVolume = False
End If
mount.bMountReadOnly = MountOption.ReadOnly
mount.bMountRemovable = MountOption.Removable
mount.bPreserveTimestamp = MountOption.PreserveTimestamp
mount.bMountManager = True
If volumePath.Contains("\\?\") Then volumePath = volumePath.Substring(4)
If volumePath.Contains("Volume{") And volumePath.LastIndexOf("}\") = volumePath.Length - 2 Then
Dim resolvedPath As String = VolumeGuidPathToDevicePath(volumePath)
If Not resolvedPath = "" Then volumePath = resolvedPath
End If
mount.wszVolume = volumePath.PadRight(TC_MAX_PATH, Chr(0))
If Not bDevice Then
'UNC
If volumePath.StartsWith("\\") Then
'Bla bla
End If
Dim bps As UInteger, flags As UInteger, d As UInteger
If GetDiskFreeSpace(Path.GetPathRoot(volumePath), d, bps, d, d) Then
mount.BytesPerSector = bps
End If
If (Not mount.bMountReadOnly) And GetVolumeInformation(Path.GetPathRoot(volumePath), Nothing, 0, Nothing, d, flags, Nothing, 0) Then
mount.bMountReadOnly = Not (flags And FILE_READ_ONLY_VOLUME) = 0
End If
End If
bResult = DeviceIoControlMount(ManagedDriver.hDriver, TC_IOCTL.MOUNT_VOLUME, mount, Marshal.SizeOf(mount), mount, Marshal.SizeOf(mount), dwResult, Nothing)
mount.VolumePassword = Nothing
mount.ProtectedHidVolPassword = Nothing
If Not bResult Then
If Marshal.GetLastWin32Error = SYSTEM_ERROR.SHARING_VIOLATION Then
'TODO
If Not mount.bExclusiveAccess Then
Return TC_ERROR.FILES_OPEN_LOCK
Else
mount.bExclusiveAccess = False
GoTo retry
End If
Return TC_ERROR.ACCESS_DENIED
End If
Return TC_ERROR.GENERIC
End If
If Not mount.nReturnCode = 0 Then Return mount.nReturnCode
'Mount successful
BroadcastDeviceChange(DBT_DEVICE.ARRIVAL, driveNo, 0)
If Not mount.bExclusiveAccess Then Return TC_ERROR.OUTOFMEMORY
Return mount.nReturnCode
End Function
TL; DR
Это очень сложная операция для объяснения в коде, проверьте исходный код, если вы хотите увидеть, как он работает, или посмотрите NuGet, если вы просто хотите его использовать. Или, если у вас есть конкретный вопрос, просто спросите.
Оригинал: я знаю, что он старый, но у меня были похожие проблемы при написании управляемого монтирования TrueCrypt. Ознакомьтесь с моим репозиторием GitHub: Управляемый драйвер TrueCrypt (VB.NET). Это было вдохновлено этой версией C#: truecryptapi dot codeplex dot com. Я переписал большую часть кода C# для более управляемого интерфейса, однако он все еще находится в стадии разработки. У меня также есть пакет NuGet, который вы можете установить в своем проекте.