diff --git a/tools/autotools/tsk_gettimes.cpp b/tools/autotools/tsk_gettimes.cpp index de388a3c0733727f94125a6fd900e95da241c419..1f8f169e96a569b2389e9ed199ea4dfa2e8480c1 100644 --- a/tools/autotools/tsk_gettimes.cpp +++ b/tools/autotools/tsk_gettimes.cpp @@ -21,12 +21,13 @@ usage() { TFPRINTF(stderr, _TSK_T - ("usage: %s [-vV] [-i imgtype] [-b dev_sector_size] [-z zone] [-s seconds] image [image]\n"), + ("usage: %s [-vVm] [-i imgtype] [-b dev_sector_size] [-z zone] [-s seconds] image [image]\n"), progname); tsk_fprintf(stderr, "\t-i imgtype: The format of the image file (use '-i list' for supported types)\n"); tsk_fprintf(stderr, "\t-b dev_sector_size: The size (in bytes) of the device sectors\n"); + tsk_fprintf(stderr, "\t-m: Calculate MD5 hash in output (slow)\n"); tsk_fprintf(stderr, "\t-v: verbose output to stderr\n"); tsk_fprintf(stderr, "\t-V: Print version\n"); tsk_fprintf(stderr, @@ -42,6 +43,7 @@ usage() class TskGetTimes:public TskAuto { public: TskGetTimes(int32_t); + TskGetTimes(int32_t, bool); virtual TSK_RETVAL_ENUM processFile(TSK_FS_FILE * fs_file, const char *path); virtual TSK_FILTER_ENUM filterVol(const TSK_VS_PART_INFO * vs_part); virtual TSK_FILTER_ENUM filterFs(TSK_FS_INFO * fs_info); @@ -50,6 +52,7 @@ class TskGetTimes:public TskAuto { private: int m_curVolAddr; int32_t m_secSkew; + bool m_compute_hash; }; @@ -57,6 +60,14 @@ TskGetTimes::TskGetTimes(int32_t a_secSkew) { m_curVolAddr = -1; m_secSkew = a_secSkew; + m_compute_hash = false; +} + +TskGetTimes::TskGetTimes(int32_t a_secSkew, bool a_compute_hash) +{ + m_curVolAddr = -1; + m_secSkew = a_secSkew; + m_compute_hash = a_compute_hash; } // Print errors as they are encountered @@ -82,10 +93,16 @@ TskGetTimes::filterFs(TSK_FS_INFO * fs_info) else volName[0] = '\0'; - if (tsk_fs_fls(fs_info, (TSK_FS_FLS_FLAG_ENUM)(TSK_FS_FLS_MAC | TSK_FS_FLS_DIR | TSK_FS_FLS_FILE | TSK_FS_FLS_FULL), - fs_info->root_inum, (TSK_FS_DIR_WALK_FLAG_ENUM)(TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC | TSK_FS_DIR_WALK_FLAG_RECURSE), volName, m_secSkew)) { - - } + TSK_FS_FLS_FLAG_ENUM fls_flags = (TSK_FS_FLS_FLAG_ENUM)(TSK_FS_FLS_MAC | TSK_FS_FLS_DIR | TSK_FS_FLS_FILE | TSK_FS_FLS_FULL); + if(m_compute_hash){ + fls_flags = (TSK_FS_FLS_FLAG_ENUM)(fls_flags | TSK_FS_FLS_HASH); + } + + if (tsk_fs_fls(fs_info, (TSK_FS_FLS_FLAG_ENUM)(fls_flags), + fs_info->root_inum, (TSK_FS_DIR_WALK_FLAG_ENUM)(TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC | TSK_FS_DIR_WALK_FLAG_RECURSE), volName, m_secSkew)) { + } + + return TSK_FILTER_SKIP; } @@ -107,6 +124,7 @@ main(int argc, char **argv1) unsigned int ssize = 0; TSK_TCHAR *cp; int32_t sec_skew = 0; + bool do_hash = false; #ifdef TSK_WIN32 // On Windows, get the wide arguments (mingw doesn't support wmain) @@ -122,7 +140,7 @@ main(int argc, char **argv1) progname = argv[0]; setlocale(LC_ALL, ""); - while ((ch = GETOPT(argc, argv, _TSK_T("b:i:s:vVz:"))) > 0) { + while ((ch = GETOPT(argc, argv, _TSK_T("b:i:s:mvVz:"))) > 0) { switch (ch) { case _TSK_T('?'): default: @@ -161,6 +179,9 @@ main(int argc, char **argv1) sec_skew = TATOI(OPTARG); break; + case _TSK_T('m'): + do_hash = true; + break; case _TSK_T('v'): tsk_verbose++; @@ -194,7 +215,7 @@ main(int argc, char **argv1) usage(); } - TskGetTimes tskGetTimes(sec_skew); + TskGetTimes tskGetTimes(sec_skew, do_hash); if (tskGetTimes.openImage(argc - OPTIND, &argv[OPTIND], imgtype, ssize)) { tsk_error_print(stderr); diff --git a/tsk/base/tsk_base.h b/tsk/base/tsk_base.h index 3de0c9b7403c0f720ee224597076d1c2031df041..9caa4404e4586b57f877e40aa96d49fae45830b5 100644 --- a/tsk/base/tsk_base.h +++ b/tsk/base/tsk_base.h @@ -473,6 +473,16 @@ documentation and/or software. void TSK_SHA_Init(TSK_SHA_CTX *); void TSK_SHA_Update(TSK_SHA_CTX *, BYTE * buffer, int count); void TSK_SHA_Final(BYTE * output, TSK_SHA_CTX *); + +/* Flags for which type of hash(es) to run */ + typedef enum{ + TSK_HASH_INVALID_ID = 0, + TSK_HASH_MD5 = 0x01, + TSK_HASH_SHA1 = 0x02 + //TSK_HASH_SHA256 = 0x04, + } TSK_HASH_ENUM; + + //@} #ifdef __cplusplus diff --git a/tsk/fs/fls_lib.c b/tsk/fs/fls_lib.c index fc28c751bb17202173edbc88a7bc81d9c4007cda..48a1d51266af0e8a5049b4e1e259844e04bc4412 100644 --- a/tsk/fs/fls_lib.c +++ b/tsk/fs/fls_lib.c @@ -50,6 +50,7 @@ static void printit(TSK_FS_FILE * fs_file, const char *a_path, const TSK_FS_ATTR * fs_attr, const FLS_DATA * fls_data) { + TSK_HASH_RESULTS hash_results; unsigned int i; if ((!(fls_data->flags & TSK_FS_FLS_FULL)) && (a_path)) { @@ -66,10 +67,18 @@ printit(TSK_FS_FILE * fs_file, const char *a_path, } - if (fls_data->flags & TSK_FS_FLS_MAC) { - tsk_fs_name_print_mac(stdout, fs_file, a_path, - fs_attr, fls_data->macpre, fls_data->sec_skew); - } + if(fls_data->flags & TSK_FS_FLS_MAC){ + if(fls_data->flags & TSK_FS_FLS_HASH){ + tsk_fs_file_hash_calc(fs_file, &hash_results, TSK_HASH_MD5); + tsk_fs_name_print_mac_md5(stdout, fs_file, a_path, + fs_attr, fls_data->macpre, fls_data->sec_skew, + hash_results.md5_digest); + } + else{ + tsk_fs_name_print_mac(stdout, fs_file, a_path, + fs_attr, fls_data->macpre, fls_data->sec_skew); + } + } else if (fls_data->flags & TSK_FS_FLS_LONG) { tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info, fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0, diff --git a/tsk/fs/fs_file.c b/tsk/fs/fs_file.c index b4e0d31517e2f062b874dca09ef99ff1d1478832..74417d832a99308e7fa89162d04b827e6ea44232 100644 --- a/tsk/fs/fs_file.c +++ b/tsk/fs/fs_file.c @@ -563,3 +563,88 @@ tsk_fs_file_get_owner_sid(TSK_FS_FILE * a_fs_file, char **sid_str) return a_fs_file->fs_info->fread_owner_sid(a_fs_file, sid_str); } + + +/** + * Internal struct used for hash calculations + */ +typedef struct { + TSK_HASH_ENUM flags; + TSK_MD5_CTX md5_context; + TSK_SHA_CTX sha1_context; +} TSK_HASH_DATA; + +/** + * Helper function for tsk_fs_file_get_md5 + */ +TSK_WALK_RET_ENUM +tsk_fs_file_hash_calc_callback(TSK_FS_FILE * file, TSK_OFF_T offset, + TSK_DADDR_T addr, char *buf, size_t size, + TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr) +{ + TSK_HASH_DATA * hash_data = (TSK_HASH_DATA *) ptr; + if (hash_data == NULL) + return TSK_WALK_CONT; + + if(hash_data->flags & TSK_HASH_MD5){ + TSK_MD5_Update(&(hash_data->md5_context), (unsigned char *) buf, (unsigned int) size); + } + + if(hash_data->flags & TSK_HASH_SHA1){ + TSK_SHA_Update(&(hash_data->sha1_context), (unsigned char *) buf, (unsigned int) size); + } + + + return TSK_WALK_CONT; +} + +/** + * Returns a string containing the md5 hash of the given file + * + * @param a_fs_file The file to calculate the hash of + * @param a_hash_results The results will be stored here (must be allocated beforehand) + * @param a_flags Indicates which hash algorithm(s) to use + * @returns 0 on success or 1 on error + */ +extern uint8_t tsk_fs_file_hash_calc(TSK_FS_FILE * a_fs_file, TSK_HASH_RESULTS * a_hash_results, TSK_HASH_ENUM a_flags){ + TSK_HASH_DATA hash_data; + int i; + + if ((a_fs_file == NULL) || (a_fs_file->fs_info == NULL) + || (a_fs_file->meta == NULL)) { + tsk_error_set_errno(TSK_ERR_FS_ARG); + tsk_error_set_errstr("tsk_fs_file_hash_calc: fs_info is NULL"); + return 1; + } + + if(a_hash_results == NULL){ + tsk_error_set_errno(TSK_ERR_FS_ARG); + tsk_error_set_errstr("tsk_fs_file_hash_calc: hash_results is NULL"); + return 1; + } + + if(a_flags & TSK_HASH_MD5){ + TSK_MD5_Init(&(hash_data.md5_context)); + } + if(a_flags & TSK_HASH_SHA1){ + TSK_SHA_Init(&(hash_data.sha1_context)); + } + + hash_data.flags = a_flags; + if(tsk_fs_file_walk(a_fs_file, TSK_FS_FILE_WALK_FLAG_NONE, + tsk_fs_file_hash_calc_callback, (void *) &hash_data)) { + tsk_error_set_errno(TSK_ERR_FS_ARG); + tsk_error_set_errstr("tsk_fs_file_hash_calc: error in file walk"); + return 1; + } + + a_hash_results->flags = a_flags; + if(a_flags & TSK_HASH_MD5){ + TSK_MD5_Final(a_hash_results->md5_digest, &(hash_data.md5_context)); + } + if(a_flags & TSK_HASH_MD5){ + TSK_SHA_Final(a_hash_results->sha1_digest, &(hash_data.sha1_context)); + } + + return 0; +} diff --git a/tsk/fs/fs_name.c b/tsk/fs/fs_name.c index aaa12c495da7b19bb0d7a7c15339d3e852884035..189ab8292044e2511db4d551597795aacdae3c21 100644 --- a/tsk/fs/fs_name.c +++ b/tsk/fs/fs_name.c @@ -582,6 +582,33 @@ void tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file, const char *a_path, const TSK_FS_ATTR * fs_attr, const char *prefix, int32_t time_skew) +{ + tsk_fs_name_print_mac_md5(hFile, fs_file, a_path, fs_attr, prefix, time_skew, NULL); +} + +/** + * \internal + * +** Print output in the format that mactime reads. +** +** If the flags in the fs_file->meta structure are set to FS_FLAG_ALLOC +** then it is assumed that the inode has been reallocated and the +** contents are not displayed +** +** fs is not required (only used for block size). + * @param hFile handle to print results to + * @param fs_file File to print details about + * @param a_path Parent directory of file (needs to end with "/") + * @param fs_attr Attribute in file that is being called for (NULL for non-NTFS) + * @param prefix Path of mounting point for image + * @param time_skew number of seconds skew to adjust time + * @param hash_results Holds the calculated md5 hash +*/ +void +tsk_fs_name_print_mac_md5(FILE * hFile, const TSK_FS_FILE * fs_file, + const char *a_path, const TSK_FS_ATTR * fs_attr, + const char *prefix, int32_t time_skew, + const unsigned char * hash_results) { char ls[12]; size_t i; @@ -600,8 +627,18 @@ tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file, isADS = 1; } - /* md5 */ - tsk_fprintf(hFile, "0|"); + /* hash + * Print out the hash buffer (if not null) + */ + if(hash_results == NULL){ + tsk_fprintf(hFile, "0|"); + } + else{ + for(i = 0;i < 16;i++){ + tsk_fprintf(hFile, "%02x", hash_results[i]); + } + tsk_fprintf(hFile, "|"); + } /* file name */ tsk_fprintf(hFile, "%s", prefix); diff --git a/tsk/fs/tsk_fs.h b/tsk/fs/tsk_fs.h index 2814434832abe172432abd9ede450b92dcb30d76..936d4ee8c3c219c465ff8172431acc4a3c7fa397 100644 --- a/tsk/fs/tsk_fs.h +++ b/tsk/fs/tsk_fs.h @@ -722,6 +722,14 @@ extern "C" { extern uint8_t tsk_fs_file_get_owner_sid(TSK_FS_FILE *, char **); + typedef struct { + TSK_HASH_ENUM flags; + unsigned char md5_digest[16]; + unsigned char sha1_digest[20]; + } TSK_HASH_RESULTS; + + extern uint8_t tsk_fs_file_hash_calc(TSK_FS_FILE *, TSK_HASH_RESULTS *, TSK_HASH_ENUM); + //@} @@ -1043,6 +1051,7 @@ extern "C" { TSK_FS_FLS_DIR = 0x08, TSK_FS_FLS_FULL = 0x10, TSK_FS_FLS_MAC = 0x20, + TSK_FS_FLS_HASH = 0x40 }; typedef enum TSK_FS_FLS_FLAG_ENUM TSK_FS_FLS_FLAG_ENUM; extern uint8_t tsk_fs_fls(TSK_FS_INFO * fs, diff --git a/tsk/fs/tsk_fs_i.h b/tsk/fs/tsk_fs_i.h index 27538e28de4e49c4039f9adf942957cbe15a56b7..944f2818d24eacc29df7ab03768372f497127703 100644 --- a/tsk/fs/tsk_fs_i.h +++ b/tsk/fs/tsk_fs_i.h @@ -162,6 +162,9 @@ extern "C" { int32_t); extern void tsk_fs_name_print_mac(FILE *, const TSK_FS_FILE *, const char *, const TSK_FS_ATTR * fs_attr, const char *, int32_t); + extern void tsk_fs_name_print_mac_md5(FILE *, const TSK_FS_FILE *, + const char *, const TSK_FS_ATTR * fs_attr, const char *, int32_t, + const unsigned char *); extern uint8_t tsk_fs_name_copy(TSK_FS_NAME * a_fs_name_to, const TSK_FS_NAME * a_fs_name_from); extern void tsk_fs_name_reset(TSK_FS_NAME * a_fs_name);