diff options
author | kavsrf <kavsrf@gmail.com> | 2016-12-04 13:40:51 +0300 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2016-12-26 00:00:02 +0100 |
commit | cd6df44d6f0e31bb81595f69691443cf1e4b21cf (patch) | |
tree | a2a181e1e616be19c01e045bef2e44f1e1b1bf11 /src | |
parent | a7f8548e2fa592123b87e47095649e5c46702ab5 (diff) | |
download | VeraCrypt-cd6df44d6f0e31bb81595f69691443cf1e4b21cf.tar.gz VeraCrypt-cd6df44d6f0e31bb81595f69691443cf1e4b21cf.zip |
Driver with support of hidden OS
Signed-off-by: kavsrf <kavsrf@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Driver/DriveFilter.c | 156 | ||||
-rw-r--r-- | src/Driver/EncryptedIoQueue.c | 59 | ||||
-rw-r--r-- | src/Driver/EncryptedIoQueue.h | 2 |
3 files changed, 191 insertions, 26 deletions
diff --git a/src/Driver/DriveFilter.c b/src/Driver/DriveFilter.c index 66f49816..b8aad224 100644 --- a/src/Driver/DriveFilter.c +++ b/src/Driver/DriveFilter.c | |||
@@ -33,6 +33,10 @@ static BOOL DeviceFilterActive = FALSE; | |||
33 | 33 | ||
34 | BOOL BootArgsValid = FALSE; | 34 | BOOL BootArgsValid = FALSE; |
35 | BootArguments BootArgs; | 35 | BootArguments BootArgs; |
36 | byte* BootSecRegionData = NULL; | ||
37 | uint32 BootSecRegionSize = 0; | ||
38 | uint32 BootPkcs5; | ||
39 | |||
36 | static uint64 BootLoaderArgsPtr; | 40 | static uint64 BootLoaderArgsPtr; |
37 | static BOOL BootDriveSignatureValid = FALSE; | 41 | static BOOL BootDriveSignatureValid = FALSE; |
38 | 42 | ||
@@ -76,10 +80,11 @@ NTSTATUS LoadBootArguments () | |||
76 | NTSTATUS status = STATUS_UNSUCCESSFUL; | 80 | NTSTATUS status = STATUS_UNSUCCESSFUL; |
77 | PHYSICAL_ADDRESS bootArgsAddr; | 81 | PHYSICAL_ADDRESS bootArgsAddr; |
78 | byte *mappedBootArgs; | 82 | byte *mappedBootArgs; |
83 | byte *mappedCryptoInfo = NULL; | ||
79 | uint16 bootLoaderArgsIndex; | 84 | uint16 bootLoaderArgsIndex; |
80 | 85 | ||
81 | KeInitializeMutex (&MountMutex, 0); | 86 | KeInitializeMutex (&MountMutex, 0); |
82 | 87 | // __debugbreak(); | |
83 | for (bootLoaderArgsIndex = 0; | 88 | for (bootLoaderArgsIndex = 0; |
84 | bootLoaderArgsIndex < sizeof(BootArgsRegions)/ sizeof(BootArgsRegions[1]) && status != STATUS_SUCCESS; | 89 | bootLoaderArgsIndex < sizeof(BootArgsRegions)/ sizeof(BootArgsRegions[1]) && status != STATUS_SUCCESS; |
85 | ++bootLoaderArgsIndex) | 90 | ++bootLoaderArgsIndex) |
@@ -126,22 +131,61 @@ NTSTATUS LoadBootArguments () | |||
126 | Dump ("BootDriveSignature = %x\n", BootArgs.BootDriveSignature); | 131 | Dump ("BootDriveSignature = %x\n", BootArgs.BootDriveSignature); |
127 | Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32); | 132 | Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32); |
128 | 133 | ||
129 | if (CacheBootPassword && BootArgs.BootPassword.Length > 0) | ||
130 | { | ||
131 | int pim = CacheBootPim? (int) (BootArgs.Flags >> 16) : 0; | ||
132 | AddPasswordToCache (&BootArgs.BootPassword, pim); | ||
133 | } | ||
134 | |||
135 | // clear fingerprint | 134 | // clear fingerprint |
136 | burn (BootLoaderFingerprint, sizeof (BootLoaderFingerprint)); | 135 | burn (BootLoaderFingerprint, sizeof (BootLoaderFingerprint)); |
136 | MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); | ||
137 | 137 | ||
138 | if (BootArgs.CryptoInfoLength > 0) | ||
139 | { | ||
140 | PHYSICAL_ADDRESS cryptoInfoAddress; | ||
141 | cryptoInfoAddress.QuadPart = BootLoaderArgsPtr + BootArgs.CryptoInfoOffset; | ||
142 | Dump ("CryptoInfo memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength); | ||
143 | |||
144 | mappedCryptoInfo = MmMapIoSpace (cryptoInfoAddress, BootArgs.CryptoInfoLength, MmCached); | ||
145 | if (mappedCryptoInfo) | ||
146 | { | ||
147 | /* Get the parameters used for booting to speed up driver startup and avoid testing irrelevant PRFs */ | ||
148 | BOOT_CRYPTO_HEADER* pBootCryptoInfo = (BOOT_CRYPTO_HEADER*) mappedCryptoInfo; | ||
149 | BootPkcs5 = pBootCryptoInfo->pkcs5; | ||
150 | |||
151 | BootSecRegionData = NULL; | ||
152 | BootSecRegionSize = 0; | ||
153 | |||
154 | if(BootArgs.CryptoInfoLength > (sizeof(BOOT_CRYPTO_HEADER) + sizeof(SECREGION_BOOT_PARAMS)) ) { | ||
155 | uint32 crc; | ||
156 | PHYSICAL_ADDRESS SecRegionAddress; | ||
157 | SECREGION_BOOT_PARAMS* SecRegionParams = (SECREGION_BOOT_PARAMS*) (mappedCryptoInfo + sizeof(BOOT_CRYPTO_HEADER) + 2); | ||
158 | byte *secRegionData = NULL; | ||
159 | |||
160 | SecRegionAddress.QuadPart = SecRegionParams->Ptr; | ||
161 | Dump ("SecRegion memory 0x%x %d\n", SecRegionAddress.LowPart, SecRegionParams->Size); | ||
162 | |||
163 | if( (SecRegionParams->Ptr != 0) && (SecRegionParams->Size > 0)) { | ||
164 | crc = GetCrc32((byte*)SecRegionParams, 12); | ||
165 | if(crc == SecRegionParams->Crc) { | ||
166 | Dump ("SecRegion crc ok\n"); | ||
167 | secRegionData = MmMapIoSpace (SecRegionAddress, SecRegionParams->Size, MmCached); | ||
168 | BootSecRegionData = TCalloc (SecRegionParams->Size); | ||
169 | if(BootSecRegionData != NULL) { | ||
170 | BootSecRegionSize = SecRegionParams->Size; | ||
171 | memcpy(BootSecRegionData, secRegionData, SecRegionParams->Size); | ||
172 | } | ||
173 | burn (secRegionData, SecRegionParams->Size); | ||
174 | MmUnmapIoSpace (secRegionData, SecRegionParams->Size); | ||
175 | } | ||
176 | // Erase boot loader scheduled keys | ||
177 | burn (mappedCryptoInfo, BootArgs.CryptoInfoLength); | ||
178 | MmUnmapIoSpace (mappedCryptoInfo, BootArgs.CryptoInfoLength); | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | } | ||
138 | status = STATUS_SUCCESS; | 183 | status = STATUS_SUCCESS; |
139 | } | 184 | } |
185 | } else { | ||
186 | MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); | ||
140 | } | 187 | } |
141 | |||
142 | MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); | ||
143 | } | 188 | } |
144 | |||
145 | return status; | 189 | return status; |
146 | } | 190 | } |
147 | 191 | ||
@@ -327,30 +371,55 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, | |||
327 | Dump ("MountDrive pdo=%p\n", Extension->Pdo); | 371 | Dump ("MountDrive pdo=%p\n", Extension->Pdo); |
328 | ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); | 372 | ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); |
329 | 373 | ||
330 | // Check boot drive signature first (header CRC search could fail if a user restored the header to a non-boot drive) | 374 | if (BootSecRegionData != NULL && BootSecRegionSize >= 1024) { |
331 | if (BootDriveSignatureValid) | ||
332 | { | ||
333 | byte mbr[TC_SECTOR_SIZE_BIOS]; | 375 | byte mbr[TC_SECTOR_SIZE_BIOS]; |
334 | 376 | DCS_DISK_ENTRY_LIST* DeList = (DCS_DISK_ENTRY_LIST*)(BootSecRegionData + 512); | |
335 | offset.QuadPart = 0; | 377 | offset.QuadPart = 0; |
336 | status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS); | 378 | status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS); |
337 | 379 | ||
338 | if (NT_SUCCESS (status) && BootArgs.BootDriveSignature != *(uint32 *) (mbr + 0x1b8)) | 380 | if (NT_SUCCESS (status) && DeList->DE[DE_IDX_DISKID].DiskId.MbrID != *(uint32 *) (mbr + 0x1b8)) |
339 | return STATUS_UNSUCCESSFUL; | 381 | return STATUS_UNSUCCESSFUL; |
340 | } | ||
341 | 382 | ||
342 | header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); | 383 | offset.QuadPart = 512; |
343 | if (!header) | 384 | status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS); |
344 | return STATUS_INSUFFICIENT_RESOURCES; | 385 | if (NT_SUCCESS (status) && memcmp(&DeList->DE[DE_IDX_DISKID].DiskId.GptID, mbr + 0x38, sizeof(DCS_GUID)) != 0) |
386 | return STATUS_UNSUCCESSFUL; | ||
345 | 387 | ||
346 | offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; | 388 | header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); |
347 | Dump ("Reading volume header at %I64u\n", offset.QuadPart); | 389 | if (!header) |
390 | return STATUS_INSUFFICIENT_RESOURCES; | ||
391 | memcpy(header, BootSecRegionData, 512); | ||
392 | // Set extra data for the disk | ||
393 | Extension->Queue.SecRegionData = BootSecRegionData; | ||
394 | Extension->Queue.SecRegionSize = BootSecRegionSize; | ||
395 | } else { | ||
396 | // Check boot drive signature first (header CRC search could fail if a user restored the header to a non-boot drive) | ||
397 | if (BootDriveSignatureValid) | ||
398 | { | ||
399 | byte mbr[TC_SECTOR_SIZE_BIOS]; | ||
348 | 400 | ||
349 | status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); | 401 | offset.QuadPart = 0; |
350 | if (!NT_SUCCESS (status)) | 402 | status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS); |
351 | { | 403 | |
352 | Dump ("TCReadDevice error %x\n", status); | 404 | if (NT_SUCCESS (status) && BootArgs.BootDriveSignature != *(uint32 *) (mbr + 0x1b8)) |
353 | goto ret; | 405 | return STATUS_UNSUCCESSFUL; |
406 | } | ||
407 | |||
408 | header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); | ||
409 | if (!header) | ||
410 | return STATUS_INSUFFICIENT_RESOURCES; | ||
411 | |||
412 | offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; | ||
413 | Dump ("Reading volume header at %I64u\n", offset.QuadPart); | ||
414 | |||
415 | status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); | ||
416 | if (!NT_SUCCESS (status)) | ||
417 | { | ||
418 | Dump ("TCReadDevice error %x\n", status); | ||
419 | goto ret; | ||
420 | } | ||
421 | Extension->Queue.SecRegionData = NULL; | ||
422 | Extension->Queue.SecRegionSize = 0; | ||
354 | } | 423 | } |
355 | 424 | ||
356 | if (headerSaltCrc32) | 425 | if (headerSaltCrc32) |
@@ -469,6 +538,41 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, | |||
469 | BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE; | 538 | BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE; |
470 | BootDriveFilterExtension->MagicNumber = TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER; | 539 | BootDriveFilterExtension->MagicNumber = TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER; |
471 | 540 | ||
541 | if (BootSecRegionData != NULL && BootSecRegionSize > 1024) { | ||
542 | DCS_DISK_ENTRY_LIST* DeList = (DCS_DISK_ENTRY_LIST*)(BootSecRegionData + 512); | ||
543 | uint32 crc; | ||
544 | uint32 crcSaved; | ||
545 | crcSaved = DeList->CRC32; | ||
546 | DeList->CRC32 = 0; | ||
547 | crc = GetCrc32((byte*)DeList, 512); | ||
548 | if(crc == crcSaved){ | ||
549 | if(DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { | ||
550 | uint64 sector = 0; | ||
551 | DCS_DEP_PWD_CACHE* pwdCache = (DCS_DEP_PWD_CACHE*)(BootSecRegionData + DeList->DE[DE_IDX_PWDCACHE].Sectors.Offset); | ||
552 | DecryptDataUnits((unsigned char*)pwdCache, (UINT64_STRUCT*)§or, 1, Extension->Queue.CryptoInfo); | ||
553 | crcSaved = pwdCache->CRC; | ||
554 | pwdCache->CRC = 0; | ||
555 | crc = GetCrc32((unsigned char*)pwdCache, 512); | ||
556 | if(crcSaved == crc && pwdCache->Count < CACHE_SIZE){ | ||
557 | uint32 i; | ||
558 | for(i = 0; i<pwdCache->Count; ++i){ | ||
559 | if (CacheBootPassword && pwdCache->Pwd[i].Length > 0) { | ||
560 | int pim = CacheBootPim? (int) (pwdCache->Pim[i]) : 0; | ||
561 | AddPasswordToCache (&pwdCache->Pwd[i], pim); | ||
562 | } | ||
563 | } | ||
564 | burn(pwdCache, sizeof(*pwdCache)); | ||
565 | } | ||
566 | } | ||
567 | } | ||
568 | } | ||
569 | |||
570 | if (CacheBootPassword && BootArgs.BootPassword.Length > 0) | ||
571 | { | ||
572 | int pim = CacheBootPim? (int) (BootArgs.Flags >> 16) : 0; | ||
573 | AddPasswordToCache (&BootArgs.BootPassword, pim); | ||
574 | } | ||
575 | |||
472 | burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword)); | 576 | burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword)); |
473 | 577 | ||
474 | { | 578 | { |
diff --git a/src/Driver/EncryptedIoQueue.c b/src/Driver/EncryptedIoQueue.c index 029a42f5..7f50ec30 100644 --- a/src/Driver/EncryptedIoQueue.c +++ b/src/Driver/EncryptedIoQueue.c | |||
@@ -225,6 +225,47 @@ static void ReleaseFragmentBuffer (EncryptedIoQueue *queue, byte *buffer) | |||
225 | } | 225 | } |
226 | } | 226 | } |
227 | 227 | ||
228 | BOOL | ||
229 | UpdateBuffer( | ||
230 | byte* buffer, | ||
231 | byte* secRegion, | ||
232 | uint64 bufferDiskOffset, | ||
233 | uint32 bufferLength, | ||
234 | BOOL doUpadte | ||
235 | ) | ||
236 | { | ||
237 | uint64 intersectStart; | ||
238 | uint32 intersectLength; | ||
239 | uint32 i; | ||
240 | DCS_DISK_ENTRY_LIST *DeList = (DCS_DISK_ENTRY_LIST*)(secRegion + 512); | ||
241 | BOOL updated = FALSE; | ||
242 | |||
243 | if (secRegion == NULL) return FALSE; | ||
244 | for (i = 0; i < DeList->Count; ++i) { | ||
245 | if (DeList->DE[i].Type == DE_Sectors) { | ||
246 | GetIntersection( | ||
247 | bufferDiskOffset, bufferLength, | ||
248 | DeList->DE[i].Sectors.Start, DeList->DE[i].Sectors.Start + DeList->DE[i].Sectors.Length - 1, | ||
249 | &intersectStart, &intersectLength | ||
250 | ); | ||
251 | if (intersectLength != 0) { | ||
252 | updated = TRUE; | ||
253 | if(doUpadte && buffer != NULL) { | ||
254 | // Dump("Subst data\n"); | ||
255 | memcpy( | ||
256 | buffer + (intersectStart - bufferDiskOffset), | ||
257 | secRegion + DeList->DE[i].Sectors.Offset + (intersectStart - DeList->DE[i].Sectors.Start), | ||
258 | intersectLength | ||
259 | ); | ||
260 | } else { | ||
261 | return TRUE; | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | return updated; | ||
267 | } | ||
268 | |||
228 | 269 | ||
229 | static VOID CompletionThreadProc (PVOID threadArg) | 270 | static VOID CompletionThreadProc (PVOID threadArg) |
230 | { | 271 | { |
@@ -260,6 +301,11 @@ static VOID CompletionThreadProc (PVOID threadArg) | |||
260 | 301 | ||
261 | DecryptDataUnits (request->Data + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); | 302 | DecryptDataUnits (request->Data + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); |
262 | } | 303 | } |
304 | // Dump("Read sector %lld count %d\n", request->Offset.QuadPart >> 9, request->Length >> 9); | ||
305 | // Update subst sectors | ||
306 | if((queue->SecRegionData != NULL) && (queue->SecRegionSize > 512)) { | ||
307 | UpdateBuffer(request->Data, queue->SecRegionData, request->Offset.QuadPart, request->Length, TRUE); | ||
308 | } | ||
263 | 309 | ||
264 | if (request->CompleteOriginalIrp) | 310 | if (request->CompleteOriginalIrp) |
265 | { | 311 | { |
@@ -609,6 +655,10 @@ static VOID MainThreadProc (PVOID threadArg) | |||
609 | DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); | 655 | DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); |
610 | } | 656 | } |
611 | } | 657 | } |
658 | // Update subst sectors | ||
659 | if((queue->SecRegionData != NULL) && (queue->SecRegionSize > 512)) { | ||
660 | UpdateBuffer(buffer, queue->SecRegionData, alignedOffset.QuadPart, alignedLength, TRUE); | ||
661 | } | ||
612 | 662 | ||
613 | memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength); | 663 | memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength); |
614 | } | 664 | } |
@@ -697,6 +747,15 @@ static VOID MainThreadProc (PVOID threadArg) | |||
697 | Dump ("Preventing write to boot loader or host protected area\n"); | 747 | Dump ("Preventing write to boot loader or host protected area\n"); |
698 | CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); | 748 | CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); |
699 | continue; | 749 | continue; |
750 | } | ||
751 | else if (item->Write | ||
752 | && (queue->SecRegionData != NULL) && (queue->SecRegionSize > 512) | ||
753 | && UpdateBuffer (NULL, queue->SecRegionData, item->OriginalOffset.QuadPart, (uint32)(item->OriginalOffset.QuadPart + item->OriginalLength - 1), FALSE)) | ||
754 | { | ||
755 | // Prevent inappropriately designed software from damaging important data | ||
756 | Dump ("Preventing write to the system GPT area\n"); | ||
757 | CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); | ||
758 | continue; | ||
700 | } | 759 | } |
701 | 760 | ||
702 | dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); | 761 | dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); |
diff --git a/src/Driver/EncryptedIoQueue.h b/src/Driver/EncryptedIoQueue.h index ffe71471..fe9365ed 100644 --- a/src/Driver/EncryptedIoQueue.h +++ b/src/Driver/EncryptedIoQueue.h | |||
@@ -117,6 +117,8 @@ typedef struct | |||
117 | LARGE_INTEGER LastPerformanceCounter; | 117 | LARGE_INTEGER LastPerformanceCounter; |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | byte* SecRegionData; | ||
121 | SIZE_T SecRegionSize; | ||
120 | } EncryptedIoQueue; | 122 | } EncryptedIoQueue; |
121 | 123 | ||
122 | 124 | ||