public static char GetFirstDriveLetterFromMask(uint driveMask, bool checkDriveType = true) { for (int i = 0; driveMask != 0; i++) { if ((driveMask & 0x01) != 0) { try { if (checkDriveType) { if (NativeDiskWrapper.CheckDriveType(string.Format(@"\\.\{0}:\", (char)('A' + i))) != 0) { return((char)('A' + i)); } } else { return((char)('A' + i)); } } catch { } } driveMask >>= 1; } return((char)0); }
public static bool CheckZipFileEncryption(string path) { if (File.Exists(path)) { using (FileStream fileStream = new FileStream(path, FileMode.Open)) using (ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Read)) { ZipArchiveEntry zipEntry = null; byte[] buffer = new byte[encryptionSignature.Length]; foreach (var entry in archive.Entries) { if (entry.FullName.EndsWith(".eimg")) { zipEntry = entry; break; } } if (zipEntry != null) { using (var zipEntryStream = zipEntry.Open()) { zipEntryStream.Read(buffer, 0, encryptionSignature.Length); } if (NativeDiskWrapper.ByteArrayCompare(buffer, encryptionSignature)) { return(true); } } } } return(false); }
public void Dispose() { for (int i = 0; i < volumeHandles.Length; i++) { if (volumeHandles[i] != IntPtr.Zero) { try { NativeDiskWrapper.RemoveLockOnVolume(volumeHandles[i]); } catch { } NativeDisk.CloseHandle(volumeHandles[i]); volumeHandles[i] = IntPtr.Zero; } } if (fileHandle != IntPtr.Zero) { NativeDisk.CloseHandle(fileHandle); fileHandle = IntPtr.Zero; } for (int i = 0; i < deviceHandles.Length; i++) { if (deviceHandles[i] != IntPtr.Zero) { NativeDisk.CloseHandle(deviceHandles[i]); deviceHandles[i] = IntPtr.Zero; } } Utils.AllowComputerSleep(); }
public static bool CheckZipFilePassword(string path, string password) { using (FileStream fileStream = new FileStream(path, FileMode.Open)) using (ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Read)) { Stream zipEntryStream = null; byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; foreach (var entry in archive.Entries) { if (entry.FullName.EndsWith(".eimg")) { zipEntryStream = entry.Open(); break; } } zipEntryStream.Read(salt, 0, encryptionSignature.Length); zipEntryStream.Read(salt, 0, salt.Length); using (RijndaelManaged rijndael = new RijndaelManaged()) { rijndael.KeySize = 256; rijndael.BlockSize = 128; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, Crypto_Iterations)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Padding = PaddingMode.Zeros; rijndael.Mode = CipherMode.CFB; try { using (CryptoStream cryptoStream = new CryptoStream(zipEntryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Read)) { int passwordLength = cryptoStream.ReadByte(); if (passwordBytes.Length != passwordLength) { return(false); } byte[] buff = new byte[passwordLength]; cryptoStream.Read(buff, 0, passwordLength); return(NativeDiskWrapper.ByteArrayCompare(buff, passwordBytes)); } } catch (CryptographicException) { return(false); } } } }
protected override bool ReadImageFromDeviceWorker(ulong sectorSize, ulong numSectors) { Stopwatch sw = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); byte[] deviceData = new byte[1024 * sectorSize]; ulong totalBytesReaded = 0; ulong bytesReaded = 0; ulong bytesToRead = sectorSize * numSectors; ulong bytesReadedPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; sw.Start(); percentStopwatch.Start(); for (ulong i = 0; i < numSectors; i += 1024) { if (cancelPending) { return(false); } readed = NativeDiskWrapper.ReadSectorDataFromHandle(deviceHandles[0], deviceData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); NativeDiskWrapper.WriteSectorDataToHandle(fileHandle, deviceData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize, readed); totalBytesReaded += (ulong)readed; bytesReaded += (ulong)readed; bytesReadedPerPercent += (ulong)readed; bytesToRead -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesReadedPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesReadedPerPercent = 0; percentStopwatch.Restart(); } if (sw.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesReaded / (sw.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesReaded, bytesToRead)); bytesReaded = 0; sw.Restart(); } } return(true); }
public static bool IsDriveReadOnly(string drive) { bool result = false; try { result = NativeDiskWrapper.CheckReadOnly(drive); } catch { } return(result); }
void ReCreateMbr(int x) { deviceHandles[x] = NativeDiskWrapper.GetHandleOnDevice(deviceIDs[x], NativeDisk.GENERIC_READ | NativeDisk.GENERIC_WRITE); var driveLayout = NativeDiskWrapper.DiskGetDriveLayoutEx(deviceHandles[x]); NativeDiskWrapper.DiskCreateDiskMBR(deviceHandles[x], 0xA5A5A5); NativeDiskWrapper.DiskUpdateProperties(deviceHandles[x]); driveLayout = NativeDiskWrapper.DiskGetDriveLayoutEx(deviceHandles[x]); driveLayout.PartitionEntry[0].PartitionNumber = 1; driveLayout.PartitionEntry[0].StartingOffset = 4 * 512; driveLayout.PartitionEntry[0].PartitionLength = (long)GetDeviceLength(deviceHandles[x]) - driveLayout.PartitionEntry[0].StartingOffset; driveLayout.PartitionEntry[0].RewritePartition = true; driveLayout.PartitionEntry[0].Mbr.PartitionType = (byte)PARTITION_TYPE.PARTITION_FAT32; NativeDiskWrapper.DiskSetDriveLayoutEx(deviceHandles[x], driveLayout); NativeDiskWrapper.DiskUpdateProperties(deviceHandles[x]); driveLayout = NativeDiskWrapper.DiskGetDriveLayoutEx(deviceHandles[x]); }
public override InitOperationResult InitReadImageFromDevice(string imagePath, bool skipUnallocated) { ulong fileSize; ulong spaceNeeded; availibleSectors = 0; sectorSize = 0; numSectors = 0; ulong freeSpace = 0; Dispose(); volumeHandles[0] = NativeDiskWrapper.GetHandleOnVolume(volumeIDs[0], NativeDisk.GENERIC_WRITE); NativeDiskWrapper.GetLockOnVolume(volumeHandles[0]); NativeDiskWrapper.UnmountVolume(volumeHandles[0]); fileHandle = NativeDiskWrapper.GetHandleOnFile(imagePath, NativeDisk.GENERIC_WRITE | NativeDisk.GENERIC_READ); deviceHandles[0] = NativeDiskWrapper.GetHandleOnDevice(deviceIDs[0], NativeDisk.GENERIC_READ); numSectors = NativeDiskWrapper.GetNumberOfSectors(deviceHandles[0], ref sectorSize); _imagePath = imagePath; if (skipUnallocated) { numSectors = GetLastUsedPartition(); } fileSize = NativeDiskWrapper.GetFilesizeInSectors(fileHandle, sectorSize); if (fileSize >= numSectors) { spaceNeeded = 0; } else { spaceNeeded = (numSectors - fileSize) * sectorSize; } if (!NativeDiskWrapper.SpaceAvailible(imagePath.Substring(0, 3), spaceNeeded, out freeSpace)) { return(new InitOperationResult(false, spaceNeeded, freeSpace, false)); } return(new InitOperationResult(true, spaceNeeded, freeSpace, false)); }
public static bool CheckRawFilePassword(string path, string password) { byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; using (FileStream fsCrypt = new FileStream(path, FileMode.Open)) { fsCrypt.Read(salt, 0, encryptionSignature.Length); fsCrypt.Read(salt, 0, salt.Length); using (RijndaelManaged rijndael = new RijndaelManaged()) { rijndael.KeySize = 256; rijndael.BlockSize = 128; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, Crypto_Iterations)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Padding = PaddingMode.Zeros; rijndael.Mode = CipherMode.CFB; try { using (CryptoStream cryptoStream = new CryptoStream(fsCrypt, rijndael.CreateDecryptor(), CryptoStreamMode.Read)) { int passwordLength = cryptoStream.ReadByte(); if (passwordBytes.Length != passwordLength) { return(false); } byte[] buff = new byte[passwordLength]; cryptoStream.Read(buff, 0, passwordLength); return(NativeDiskWrapper.ByteArrayCompare(buff, passwordBytes)); } } catch (CryptographicException) { return(false); } } } }
public static ulong GetDeviceLength(int deviceID) { ulong length = 0; IntPtr deviceHandle = NativeDiskWrapper.GetHandleOnDevice(deviceID, NativeDisk.GENERIC_READ); unsafe { int returnLength = 0; IntPtr lengthPtr = new IntPtr(&length); NativeDisk.DeviceIoControl(deviceHandle, NativeDisk.IOCTL_DISK_GET_LENGTH_INFO, IntPtr.Zero, 0, lengthPtr, sizeof(ulong), ref returnLength, IntPtr.Zero); } NativeDisk.CloseHandle(deviceHandle); return(length); }
public Disk(char[] driveLetters) { deviceIDs = new int[driveLetters.Length]; volumeIDs = new int[driveLetters.Length]; volumeHandles = new IntPtr[driveLetters.Length]; deviceHandles = new IntPtr[driveLetters.Length]; DriveLetters = driveLetters; for (int i = 0; i < driveLetters.Length; i++) { deviceIDs[i] = NativeDiskWrapper.CheckDriveType(string.Format(@"\\.\{0}:\", DriveLetters[i])); volumeIDs[i] = DriveLetters[i] - 'A'; volumeHandles[i] = deviceHandles[i] = IntPtr.Zero; } Utils.PreventComputerSleep(); }
public static bool CheckRawFileEncryption(string path) { if (File.Exists(path)) { using (FileStream fs = new FileStream(path, FileMode.Open)) { byte[] buffer = new byte[encryptionSignature.Length]; fs.Read(buffer, 0, encryptionSignature.Length); if (NativeDiskWrapper.ByteArrayCompare(buffer, encryptionSignature)) { return(true); } } } return(false); }
public static char[] GetLogicalDrives() { List <char> drives = new List <char>(); uint drivesMask = NativeDiskWrapper.GetLogicalDrives(); for (int i = 0; drivesMask != 0; i++) { if ((drivesMask & 0x01) != 0) { try { if (NativeDiskWrapper.CheckDriveType(string.Format(@"\\.\{0}:\", (char)('A' + i))) != 0) { drives.Add((char)('A' + i)); } } catch { } } drivesMask >>= 1; } return(drives.ToArray()); }
protected bool ReadImageFromDeviceCryptoWorker(ulong sectorSize, ulong numSectors) { Stopwatch sw = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); byte[] deviceData = new byte[1024 * sectorSize]; ulong totalBytesReaded = 0; ulong bytesReaded = 0; ulong bytesToRead = sectorSize * numSectors; ulong bytesReadedPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; sw.Start(); percentStopwatch.Start(); using (FileStream fileStream = new FileStream(new SafeFileHandle(fileHandle, false), FileAccess.ReadWrite)) using (RijndaelManaged rijndael = new RijndaelManaged()) { byte[] salt = GenerateRandomSalt(); byte[] passwordBytes = Encoding.UTF8.GetBytes(password); fileStream.Write(encryptionSignature, 0, encryptionSignature.Length); fileStream.Write(salt, 0, salt.Length); rijndael.KeySize = 256; rijndael.BlockSize = 128; rijndael.Padding = PaddingMode.Zeros; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, Crypto_Iterations)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Mode = CipherMode.CFB; using (CryptoStream cryptoStream = new CryptoStream(fileStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write)) { cryptoStream.WriteByte((byte)passwordBytes.Length); cryptoStream.Write(passwordBytes, 0, passwordBytes.Length); for (ulong i = 0; i < numSectors; i += 1024) { if (cancelPending) { return(false); } readed = NativeDiskWrapper.ReadSectorDataFromHandle(deviceHandles[0], deviceData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); cryptoStream.Write(deviceData, 0, readed); totalBytesReaded += (ulong)readed; bytesReaded += (ulong)readed; bytesReadedPerPercent += (ulong)readed; bytesToRead -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesReadedPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesReadedPerPercent = 0; percentStopwatch.Restart(); } if (sw.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesReaded / (sw.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesReaded, bytesToRead)); bytesReaded = 0; sw.Restart(); } } } } return(true); }
public override VerifyInitOperationResult InitVerifyImageAndDevice(string imagePath, bool skipUnallocated) { ulong fileSize; availibleSectors = 0; sectorSize = 0; numSectors = 0; Dispose(); for (int i = 0; i < volumeHandles.Length; i++) { volumeHandles[i] = NativeDiskWrapper.GetHandleOnVolume(volumeIDs[i], NativeDisk.GENERIC_WRITE); NativeDiskWrapper.GetLockOnVolume(volumeHandles[i]); NativeDiskWrapper.UnmountVolume(volumeHandles[i]); } fileHandle = NativeDiskWrapper.GetHandleOnFile(imagePath, NativeDisk.GENERIC_READ); for (int i = 0; i < volumeHandles.Length; i++) { deviceHandles[i] = NativeDiskWrapper.GetHandleOnDevice(deviceIDs[i], NativeDisk.GENERIC_READ); } _imagePath = imagePath; numSectors = NativeDiskWrapper.GetNumberOfSectors(deviceHandles[0], ref sectorSize); if (skipUnallocated) { numSectors = GetLastUsedPartition(); } else { for (int i = 0; i < deviceHandles.Length; i++) { var sectors = NativeDiskWrapper.GetNumberOfSectors(deviceHandles[i], ref sectorSize); if (sectors < numSectors) { numSectors = sectors; } } } if (useEncryption) { int paddingSize = 16 - ((1 + password.Length) % 16); fileSize = NativeDiskWrapper.GetFilesizeInSectors(fileHandle, sectorSize, encryptionSignature.Length + 33 + password.Length + paddingSize); } else { fileSize = NativeDiskWrapper.GetFilesizeInSectors(fileHandle, sectorSize); } if (fileSize == numSectors) { return(new VerifyInitOperationResult(true, fileSize * sectorSize, numSectors * sectorSize)); } else { return(new VerifyInitOperationResult(false, fileSize * sectorSize, numSectors * sectorSize)); } }
protected override async Task <bool> WriteImageToDeviceWorker(ulong sectorSize, ulong numSectors) { Stopwatch msStopwatch = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); byte[] imageData = new byte[1024 * sectorSize]; ulong totalBytesWritten = 0; ulong bytesWritten = 0; ulong bytesToWrite = sectorSize * numSectors; ulong bytesWrittenPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; List <Task> taskList = new List <Task>(deviceHandles.Length); msStopwatch.Start(); percentStopwatch.Start(); for (ulong i = 0; i < numSectors; i += 1024) { taskList.Clear(); if (cancelPending) { return(false); } readed = NativeDiskWrapper.ReadSectorDataFromHandle(fileHandle, imageData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); foreach (var deviceHandle in deviceHandles) { taskList.Add(NativeDiskWrapper.WriteSectorDataToHandleAsync(deviceHandle, imageData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize)); } await Task.WhenAll(taskList); totalBytesWritten += (ulong)readed; bytesWritten += (ulong)readed; bytesWrittenPerPercent += (ulong)readed; bytesToWrite -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesWrittenPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesWrittenPerPercent = 0; percentStopwatch.Restart(); } if (msStopwatch.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesWritten / (msStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesWritten, bytesToWrite)); bytesWritten = 0; msStopwatch.Restart(); } } return(true); }
public override InitOperationResult InitWriteImageToDevice(string imagePath) { availibleSectors = 0; sectorSize = 0; numSectors = 0; int smallestDeviceIndex = 0; Dispose(); for (int i = 0; i < volumeHandles.Length; i++) { volumeHandles[i] = NativeDiskWrapper.GetHandleOnVolume(volumeIDs[i], NativeDisk.GENERIC_WRITE); NativeDiskWrapper.GetLockOnVolume(volumeHandles[i]); NativeDiskWrapper.UnmountVolume(volumeHandles[i]); } fileHandle = NativeDiskWrapper.GetHandleOnFile(imagePath, NativeDisk.GENERIC_READ); for (int i = 0; i < volumeHandles.Length; i++) { deviceHandles[i] = NativeDiskWrapper.GetHandleOnDevice(deviceIDs[i], NativeDisk.GENERIC_WRITE | NativeDisk.GENERIC_READ); } availibleSectors = NativeDiskWrapper.GetNumberOfSectors(deviceHandles[0], ref sectorSize); for (int i = 1; i < deviceHandles.Length; i++) { var sectors = NativeDiskWrapper.GetNumberOfSectors(deviceHandles[i], ref sectorSize); if (sectors < availibleSectors) { availibleSectors = sectors; smallestDeviceIndex = i; } } if (useEncryption) { int paddingSize = 16 - ((1 + password.Length) % 16); numSectors = NativeDiskWrapper.GetFilesizeInSectors(fileHandle, sectorSize, encryptionSignature.Length + 33 + password.Length + paddingSize); } else { numSectors = NativeDiskWrapper.GetFilesizeInSectors(fileHandle, sectorSize); } _imagePath = imagePath; if (numSectors > availibleSectors) { bool dataFound = false; ulong i = availibleSectors; ulong nextChunkSize = 0; byte[] sectorData = new byte[1024 * sectorSize]; if (useEncryption) { using (FileStream fs = new FileStream(new SafeFileHandle(fileHandle, false), FileAccess.Read)) using (RijndaelManaged rijndael = new RijndaelManaged()) { byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; fs.Read(salt, 0, encryptionSignature.Length); fs.Read(salt, 0, salt.Length); rijndael.KeySize = 256; rijndael.BlockSize = 128; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Padding = PaddingMode.Zeros; rijndael.Mode = CipherMode.CFB; using (CryptoStream cs = new CryptoStream(fs, rijndael.CreateDecryptor(), CryptoStreamMode.Read)) { int passLen = cs.ReadByte(); cs.Read(sectorData, 0, passLen); { while (i < numSectors && !dataFound) { nextChunkSize = ((numSectors - i) >= 1024) ? 1024 : (numSectors - i); int dataLength = cs.Read(sectorData, 0, (int)(nextChunkSize * sectorSize)); for (int x = 0; x < dataLength; x++) { if (sectorData[x] != 0) { dataFound = true; break; } } i += nextChunkSize; } } } } } else { while (i < numSectors && !dataFound) { nextChunkSize = ((numSectors - i) >= 1024) ? 1024 : (numSectors - i); int dataLength = NativeDiskWrapper.ReadSectorDataFromHandle(fileHandle, sectorData, i, nextChunkSize, sectorSize); for (int x = 0; x < dataLength; x++) { if (sectorData[x] != 0) { dataFound = true; break; } } i += nextChunkSize; } } return(new InitOperationResult(false, numSectors * sectorSize, availibleSectors * sectorSize, dataFound, DriveLetters[smallestDeviceIndex])); } return(new InitOperationResult(true, numSectors * sectorSize, availibleSectors * sectorSize, false)); }
protected override async Task <bool> VerifyImageAndDeviceWorkerAsync(IntPtr fileHandle, ulong sectorSize, ulong numSectors) { byte[] fileData = new byte[1024 * sectorSize]; Stopwatch msStopwatch = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); ulong totalBytesVerified = 0; ulong bytesVerified = 0; ulong bytesToVerify = sectorSize * numSectors; ulong bytesVerifiedPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; List <Task <bool> > taskList = new List <Task <bool> >(deviceHandles.Length); byte[][] deviceData = new byte[deviceHandles.Length][]; int failedDeviceIndex = 0; for (int i = 0; i < deviceHandles.Length; i++) { deviceData[i] = new byte[1024 * sectorSize]; } msStopwatch.Start(); percentStopwatch.Start(); for (ulong i = 0; i < numSectors; i += 1024) { taskList.Clear(); if (cancelPending) { return(false); } readed = NativeDiskWrapper.ReadSectorDataFromHandle(fileHandle, fileData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); for (int x = 0; x < deviceHandles.Length; x++) { int index = x; taskList.Add(Task.Run(() => { NativeDiskWrapper.ReadSectorDataFromHandle(deviceHandles[index], deviceData[index], i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); if (!NativeDiskWrapper.ByteArrayCompare(fileData, deviceData[index])) { failedDeviceIndex = index; return(false); } else { return(true); } })); } await Task.WhenAll(taskList); foreach (var task in taskList) { if (!task.Result) { for (ulong x = 0; x < 1024 * sectorSize; x++) { if (deviceData[failedDeviceIndex][x] != fileData[x]) { throw new Exception(string.Format("Verify found different data. Device {0}:\\ at byte {1:n0}, file data: 0x{2:X2}, device data: 0x{3:X2}", DriveLetters[failedDeviceIndex], i * sectorSize + x, deviceData[failedDeviceIndex][x], fileData[x])); } } return(false); } } totalBytesVerified += (ulong)readed; bytesVerified += (ulong)readed; bytesVerifiedPerPercent += (ulong)readed; bytesToVerify -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesVerifiedPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesVerifiedPerPercent = 0; percentStopwatch.Restart(); } if (msStopwatch.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesVerified / (msStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesVerified, bytesToVerify)); bytesVerified = 0; msStopwatch.Restart(); } } return(true); }
protected async Task <bool> WriteImageToDeviceCryptoWorker(ulong sectorSize, ulong numSectors) { Stopwatch msStopwatch = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); byte[] imageData = new byte[1024 * sectorSize]; ulong totalBytesWritten = 0; ulong bytesWritten = 0; ulong bytesToWrite = sectorSize * numSectors; ulong bytesWrittenPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; List <Task> taskList = new List <Task>(deviceHandles.Length); byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; msStopwatch.Start(); percentStopwatch.Start(); using (FileStream inputFile = new FileStream(new SafeFileHandle(fileHandle, false), FileAccess.Read)) using (RijndaelManaged rijndael = new RijndaelManaged()) { inputFile.Read(salt, 0, encryptionSignature.Length); inputFile.Read(salt, 0, salt.Length); rijndael.KeySize = 256; rijndael.BlockSize = 128; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Padding = PaddingMode.Zeros; rijndael.Mode = CipherMode.CFB; using (CryptoStream cs = new CryptoStream(inputFile, rijndael.CreateDecryptor(), CryptoStreamMode.Read)) { int passLen = cs.ReadByte(); cs.Read(imageData, 0, passLen); for (ulong i = 0; i < numSectors; i += 1024) { taskList.Clear(); if (cancelPending) { return(false); } readed = cs.Read(imageData, 0, imageData.Length); foreach (var deviceHandle in deviceHandles) { taskList.Add(NativeDiskWrapper.WriteSectorDataToHandleAsync(deviceHandle, imageData, i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize)); } await Task.WhenAll(taskList); totalBytesWritten += (ulong)readed; bytesWritten += (ulong)readed; bytesWrittenPerPercent += (ulong)readed; bytesToWrite -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesWrittenPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesWrittenPerPercent = 0; percentStopwatch.Restart(); } if (msStopwatch.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesWritten / (msStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesWritten, bytesToWrite)); bytesWritten = 0; msStopwatch.Restart(); } } } } return(true); }
public static DiskPartitionInfo GetDiskPartitionInfo(char driveLetter) { int deviceID = NativeDiskWrapper.CheckDriveType(string.Format(@"\\.\{0}:\", driveLetter)); IntPtr deviceHandle = NativeDiskWrapper.GetHandleOnDevice(deviceID, NativeDisk.GENERIC_READ); uint partitionTableSize = 0; DiskPartitionInfo partitionsInfo = new DiskPartitionInfo(); var partitionInfo = NativeDiskWrapper.GetDiskPartitionInfo(deviceHandle); partitionsInfo.DiskTotalSize = GetDeviceLength(deviceID); if (partitionInfo.PartitionStyle == PARTITION_STYLE.MasterBootRecord) { partitionsInfo.PartitionType = PartitionType.MBR; partitionTableSize = 512; unsafe { byte *data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandle, 0, 1, 512); for (int i = 0; i < 4; i++) { ulong partitionStartSector = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1BE + 8 + 16 * i); ulong partitionNumSectors = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1BE + 12 + 16 * i); if (partitionStartSector + partitionNumSectors > 0) { partitionsInfo.PartitionSizes.Add(partitionNumSectors * 512); } } } } else if (partitionInfo.PartitionStyle == PARTITION_STYLE.GuidPartitionTable) { partitionsInfo.PartitionType = PartitionType.GPT; partitionTableSize = 17408; unsafe { byte *data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandle, 0, 1, 512); uint gptHeaderOffset = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1C6); data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandle, gptHeaderOffset, 1, 512); ulong partitionTableSector = (ulong)Marshal.ReadInt64(new IntPtr(data), 0x48); uint noOfPartitionEntries = (uint)Marshal.ReadInt32(new IntPtr(data), 0x50); uint sizeOfPartitionEntry = (uint)Marshal.ReadInt32(new IntPtr(data), 0x54); data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandle, partitionTableSector, (512 / sizeOfPartitionEntry) * noOfPartitionEntries, 512); for (int i = 0; i < noOfPartitionEntries; i++) { ulong partitionStartSector = (ulong)Marshal.ReadInt64(new IntPtr(data), (int)(0x20 + sizeOfPartitionEntry * i)); ulong partitionNumSectors = (ulong)Marshal.ReadInt64(new IntPtr(data), (int)(0x28 + sizeOfPartitionEntry * i)); if (partitionStartSector + partitionNumSectors > 0) { partitionsInfo.PartitionSizes.Add(partitionNumSectors * 512); } } } } else { partitionsInfo.PartitionType = PartitionType.RAW; } NativeDisk.CloseHandle(deviceHandle); partitionsInfo.UnallocatedSize = partitionsInfo.DiskTotalSize - (partitionsInfo.PartitionSizes.Sum() + partitionTableSize); return(partitionsInfo); }
protected async Task <bool> VerifyImageAndDeviceCryptoWorkerAsync(IntPtr fileHandle, ulong sectorSize, ulong numSectors) { byte[] fileData = new byte[1024 * sectorSize]; Stopwatch msStopwatch = new Stopwatch(); Stopwatch percentStopwatch = new Stopwatch(); ulong totalBytesVerified = 0; ulong bytesVerified = 0; ulong bytesToVerify = sectorSize * numSectors; ulong bytesVerifiedPerPercent = 0; int lastProgress = 0; int progress = 0; int readed = 0; List <Task <bool> > taskList = new List <Task <bool> >(deviceHandles.Length); byte[][] deviceData = new byte[deviceHandles.Length][]; int failedDeviceIndex = 0; byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; for (int i = 0; i < deviceHandles.Length; i++) { deviceData[i] = new byte[1024 * sectorSize]; } msStopwatch.Start(); percentStopwatch.Start(); using (FileStream inputFile = new FileStream(new SafeFileHandle(fileHandle, false), FileAccess.Read)) using (RijndaelManaged rijndael = new RijndaelManaged()) { inputFile.Seek(0, SeekOrigin.Begin); inputFile.Read(salt, 0, encryptionSignature.Length); inputFile.Read(salt, 0, salt.Length); rijndael.KeySize = 256; rijndael.BlockSize = 128; using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000)) { rijndael.Key = key.GetBytes(rijndael.KeySize / 8); rijndael.IV = key.GetBytes(rijndael.BlockSize / 8); } rijndael.Padding = PaddingMode.Zeros; rijndael.Mode = CipherMode.CFB; using (CryptoStream cs = new CryptoStream(inputFile, rijndael.CreateDecryptor(), CryptoStreamMode.Read)) { int passLen = cs.ReadByte(); cs.Read(fileData, 0, passLen); for (ulong i = 0; i < numSectors; i += 1024) { taskList.Clear(); if (cancelPending) { return(false); } readed = cs.Read(fileData, 0, fileData.Length); for (int x = 0; x < deviceHandles.Length; x++) { int index = x; taskList.Add(Task.Run(() => { NativeDiskWrapper.ReadSectorDataFromHandle(deviceHandles[index], deviceData[index], i, (numSectors - i >= 1024) ? 1024 : (numSectors - i), sectorSize); if (!NativeDiskWrapper.ByteArrayCompare(fileData, deviceData[index])) { failedDeviceIndex = index; return(false); } else { return(true); } })); } await Task.WhenAll(taskList); foreach (var task in taskList) { if (!task.Result) { for (ulong x = 0; x < 1024 * sectorSize; x++) { if (deviceData[failedDeviceIndex][x] != fileData[x]) { throw new Exception(string.Format("Verify found different data. Device {0}:\\ at byte {1:n0}, file data: 0x{2:X2}, device data: 0x{3:X2}", DriveLetters[failedDeviceIndex], i * sectorSize + x, deviceData[failedDeviceIndex][x], fileData[x])); } } return(false); } } totalBytesVerified += (ulong)readed; bytesVerified += (ulong)readed; bytesVerifiedPerPercent += (ulong)readed; bytesToVerify -= (ulong)readed; progress = (int)(i / (numSectors / 100.0)) + 1; if (progress != lastProgress) { ulong averageBps = (ulong)(bytesVerifiedPerPercent / (percentStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressChanged?.Invoke(this, new OperationProgressChangedEventArgs(progress, averageBps, currentDiskOperation)); lastProgress = progress; bytesVerifiedPerPercent = 0; percentStopwatch.Restart(); } if (msStopwatch.ElapsedMilliseconds >= 1000) { ulong averageBps = (ulong)(bytesVerified / (msStopwatch.ElapsedMilliseconds / 1000.0)); OperationProgressReport?.Invoke(this, new OperationProgressReportEventArgs(averageBps, totalBytesVerified, bytesToVerify)); bytesVerified = 0; msStopwatch.Restart(); } } } } return(true); }
public ulong GetLastUsedPartition() { ulong[] numSectorsArr = new ulong[deviceHandles.Length]; for (int x = 0; x < deviceHandles.Length; x++) { var partitionInfo = NativeDiskWrapper.GetDiskPartitionInfo(deviceHandles[x]); if (partitionInfo.PartitionStyle == PARTITION_STYLE.MasterBootRecord) { numSectorsArr[x] = 1; unsafe { byte *data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandles[x], 0, 1, sectorSize); for (int i = 0; i < 4; i++) { ulong partitionStartSector = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1BE + 8 + 16 * i); ulong partitionNumSectors = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1BE + 12 + 16 * i); if (partitionStartSector + partitionNumSectors > numSectorsArr[x]) { numSectorsArr[x] = partitionStartSector + partitionNumSectors; } } } } else if (partitionInfo.PartitionStyle == PARTITION_STYLE.GuidPartitionTable) { numSectorsArr[x] = 1; unsafe { byte *data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandles[x], 0, 1, sectorSize); uint gptHeaderOffset = (uint)Marshal.ReadInt32(new IntPtr(data), 0x1C6); data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandles[x], gptHeaderOffset, 1, sectorSize); ulong partitionTableSector = (ulong)Marshal.ReadInt64(new IntPtr(data), 0x48); uint noOfPartitionEntries = (uint)Marshal.ReadInt32(new IntPtr(data), 0x50); uint sizeOfPartitionEntry = (uint)Marshal.ReadInt32(new IntPtr(data), 0x54); data = NativeDiskWrapper.ReadSectorDataPointerFromHandle(deviceHandles[x], partitionTableSector, (sectorSize / sizeOfPartitionEntry) * noOfPartitionEntries, sectorSize); for (int i = 0; i < noOfPartitionEntries; i++) { ulong partitionStartSector = (ulong)Marshal.ReadInt64(new IntPtr(data), (int)(0x20 + sizeOfPartitionEntry * i)); ulong partitionNumSectors = (ulong)Marshal.ReadInt64(new IntPtr(data), (int)(0x28 + sizeOfPartitionEntry * i)); if (partitionStartSector + partitionNumSectors > numSectorsArr[x]) { numSectorsArr[x] = partitionStartSector + partitionNumSectors; } } } } } for (int i = 1; i < deviceHandles.Length; i++) { if (numSectorsArr[0] != numSectorsArr[i]) { throw new Exception("Devices have different partitions size.\nVerifying will not be started."); } } return(numSectorsArr[0]); }