diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp index 03a2323da51af56fdf060fd3bdedfd0e7ded254a..8f633247d8159c1357f4e5943a84317080183805 100755 --- a/tsk/auto/auto.cpp +++ b/tsk/auto/auto.cpp @@ -322,8 +322,12 @@ TskAuto::findFilesInVs(TSK_OFF_T a_start, TSK_VS_TYPE_ENUM a_vtype) TSK_VS_INFO *vs_info; // Use mm_walk to get the volumes if ((vs_info = tsk_vs_open(m_img_info, a_start, a_vtype)) == NULL) { - /* we're going to ignore this error to avoid confusion if the - * fs_open passes. */ + + /* If the error code is for encryption, we will register it. Otherwise, + * ignore this error to avoid confusion if the fs_open passes. */ + if (tsk_error_get_errno() == TSK_ERR_VS_ENCRYPTED) { + registerError(); + } tsk_error_reset(); if(tsk_verbose) diff --git a/tsk/auto/is_image_supported.cpp b/tsk/auto/is_image_supported.cpp index 95f9448daa0e2847b4b559341b7b21ff97ea4cef..ec9d4f8b88f3b6eab05cce6d2b07fbbbae7b2954 100644 --- a/tsk/auto/is_image_supported.cpp +++ b/tsk/auto/is_image_supported.cpp @@ -71,7 +71,8 @@ uint8_t TskIsImageSupported::handleError() TSK_ERROR_INFO* lastError = tsk_error_get_info(); if (lastError != NULL) { uint32_t errCode = lastError->t_errno; - if (errCode == TSK_ERR_FS_ENCRYPTED) { + + if (errCode == TSK_ERR_FS_ENCRYPTED || errCode == TSK_ERR_VS_ENCRYPTED) { tsk_error_print(stdout); m_wasEncryptionFound = true; } diff --git a/tsk/base/tsk_base.h b/tsk/base/tsk_base.h index d9e5604da5d761dc3dc3ea61a9343bf5f3325045..3a2f2fcb7573564b848454e8b42ceefd01b8d505 100644 --- a/tsk/base/tsk_base.h +++ b/tsk/base/tsk_base.h @@ -332,7 +332,8 @@ extern "C" { #define TSK_ERR_VS_BUF (TSK_ERR_VS | 5) #define TSK_ERR_VS_BLK_NUM (TSK_ERR_VS | 6) #define TSK_ERR_VS_ARG (TSK_ERR_VS | 7) -#define TSK_ERR_VS_MAX 8 +#define TSK_ERR_VS_ENCRYPTED (TSK_ERR_VS | 8) +#define TSK_ERR_VS_MAX 9 #define TSK_ERR_POOL_UNKTYPE (TSK_ERR_POOL | 0) #define TSK_ERR_POOL_UNSUPTYPE (TSK_ERR_IMG | 1) diff --git a/tsk/base/tsk_error.c b/tsk/base/tsk_error.c index 20965db5c7acabcaa34d0d4e3b268c6ee7de871b..cda9c369397ce2bb639415eab431cbb6a15e6fcc 100644 --- a/tsk/base/tsk_error.c +++ b/tsk/base/tsk_error.c @@ -55,6 +55,7 @@ static const char *tsk_err_mm_str[TSK_ERR_VS_MAX] = { "Invalid buffer size", // 5 "Invalid sector address", "Invalid API argument", + "Encryption detected", }; static const char *tsk_err_fs_str[TSK_ERR_FS_MAX] = { diff --git a/tsk/util/detect_encryption.c b/tsk/util/detect_encryption.c index ebe81d7ec2c3ee6d308749c3450fed716882e534..1464f130d0f5dc54ee261a20ffda361c49473ab5 100644 --- a/tsk/util/detect_encryption.c +++ b/tsk/util/detect_encryption.c @@ -40,14 +40,65 @@ detectBitLocker(const char * buf, size_t len) { // Look for the signature near the beginning of the buffer const char * signature = "-FVE-FS-"; - return detectSignature(signature, strlen(signature), 0, 32, buf, len); + return detectSignature(signature, strlen(signature), 0, 16, buf, len); } -// Returns 1 if FileVault is found, 0 otherwise +// Returns 1 if FileVault signature is found, 0 otherwise int detectFileVault(const char * buf, size_t len) { - // Look for the signature near the beginning of the buffer const char * signature = "encrdsa"; + return detectSignature(signature, strlen(signature), 0, 0, buf, len); +} + +// Returns 1 if Check Point signature is found, 0 otherwise +int +detectCheckPoint(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer + const char * signature = "Protect"; + return detectSignature(signature, strlen(signature), 80, 100, buf, len); +} + +// Returns 1 if McAfee Safeboot signature is found, 0 otherwise +int +detectMcAfee(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer. Check two capitalizations. + const char * signature = "Safeboot"; + const char * altSignature = "SafeBoot"; + return (detectSignature(signature, strlen(signature), 0, 32, buf, len) + | detectSignature(altSignature, strlen(altSignature), 0, 32, buf, len)); +} + +// Returns 1 if Guardian Edge signature is found, 0 otherwise +int +detectGuardianEdge(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer + const char * signature = "PCGM"; + return detectSignature(signature, strlen(signature), 0, 32, buf, len); +} + +// Returns 1 if Sophos Safeguard signature is found, 0 otherwise +int +detectSophos(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer + const char * signature = "SGM400"; + const char * altSignature = "SGE400"; + return (detectSignature(signature, strlen(signature), 110, 150, buf, len) + | detectSignature(altSignature, strlen(altSignature), 110, 150, buf, len)); +} + +// Returns 1 if WinMagic SecureDoc signature is found, 0 otherwise +int +detectWinMagic(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer + const char * signature = "WMSD"; + return detectSignature(signature, strlen(signature), 236, 256, buf, len); +} + +// Returns 1 if Symantec PGP signature is found, 0 otherwise +int +detectSymantecPGP(const char * buf, size_t len) { + // Look for the signature near the beginning of the buffer + const char * signature = "\xeb\x48\x90PGPGUARD"; return detectSignature(signature, strlen(signature), 0, 32, buf, len); } @@ -167,5 +218,94 @@ detectVolumeEncryption(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) { return result; } +/** +* Detect full disk encryption in the image starting at the given offset. +* May return null on error. Note that client is responsible for freeing the result. +* +* @param img_info The open image +* @param offset The offset for the beginning of the image TODO TODO do we need this?? +* +* @return encryption_detected_result containing the result of the check. null for certain types of errors. +*/ +encryption_detected_result* +detectDiskEncryption(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) { + + encryption_detected_result* result = (encryption_detected_result*)tsk_malloc(sizeof(encryption_detected_result)); + if (result == NULL) { + return result; + } + result->encryptionType = ENCRYPTION_DETECTED_NONE; + result->desc[0] = '\0'; + + if (img_info == NULL) { + return result; + } + if (offset > (uint64_t)img_info->size) { + return result; + } + + // Read the beginning of the image. There should be room for all the signature searches. + size_t len = 1024; + char* buf = (char*)tsk_malloc(len); + if (buf == NULL) { + return result; + } + if (tsk_img_read(img_info, offset, buf, len) != len) { + free(buf); + return result; + } + + // Look for Symatec PGP signature + if (detectSymantecPGP(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "Symantec PGP encryption detected"); + free(buf); + return result; + } + + // Look for McAfee Safeboot signature + if (detectMcAfee(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "McAfee Safeboot encryption detected"); + free(buf); + return result; + } + + // Look for Sophos Safeguard + if (detectSophos(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "Sophos Safeguard encryption detected"); + free(buf); + return result; + } + + // Look for Guardian Edge signature + if (detectGuardianEdge(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "Guardian Edge encryption detected"); + free(buf); + return result; + } + + // Look for Check Point signature + if (detectCheckPoint(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "Check Point full disk encryption detected"); + free(buf); + return result; + } + + // Look for WinMagic SecureDoc signature + if (detectWinMagic(buf, len)) { + result->encryptionType = ENCRYPTION_DETECTED_SIGNATURE; + snprintf(result->desc, TSK_ERROR_STRING_MAX_LENGTH, "WinMagic SecureDoc encryption detected"); + free(buf); + return result; + } + printf("No disk encryption found\n"); + fflush(stdout); + free(buf); + return result; +} diff --git a/tsk/util/detect_encryption.h b/tsk/util/detect_encryption.h index eb58578d830d325d3aebc3fac72a06fbdf7ee8c4..1c60137fd055929341479e4c4e7a2a1f653c15ee 100644 --- a/tsk/util/detect_encryption.h +++ b/tsk/util/detect_encryption.h @@ -31,4 +31,6 @@ typedef struct encryption_detected_result { encryption_detected_result* detectVolumeEncryption(TSK_IMG_INFO * img_info, TSK_DADDR_T offset); +encryption_detected_result* detectDiskEncryption(TSK_IMG_INFO * img_info, TSK_DADDR_T offset); + #endif \ No newline at end of file diff --git a/tsk/vs/mm_open.c b/tsk/vs/mm_open.c index f8bdce2e9759ad7c7a9b174003436608c6b46029..49f0c00d64598b537a67f68b5ede639be9761f67 100644 --- a/tsk/vs/mm_open.c +++ b/tsk/vs/mm_open.c @@ -15,6 +15,7 @@ */ #include "tsk_vs_i.h" +#include "tsk\util\detect_encryption.h" /** @@ -175,7 +176,22 @@ tsk_vs_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, if (vs_set == NULL) { tsk_error_reset(); - tsk_error_set_errno(TSK_ERR_VS_UNKTYPE); + + // Check whether the volume system appears to be encrypted. + // Note that detectVolumeEncryption does not do an entropy calculation - high entropy + // files will be reported by tsk_fs_open_img(). + encryption_detected_result* result = detectDiskEncryption(img_info, offset); + if (result != NULL) { + if (result->encryptionType == ENCRYPTION_DETECTED_SIGNATURE) { + tsk_error_set_errno(TSK_ERR_VS_ENCRYPTED); + tsk_error_set_errstr(result->desc); + } + free(result); + result = NULL; + } + else { + tsk_error_set_errno(TSK_ERR_VS_UNKTYPE); + } return NULL; }