📄 hk_index.c
字号:
/* * The Sleuth Kit * * Brian Carrier [carrier <at> sleuthkit [dot] org] * Copyright (c) 2003-2008 Brian Carrier. All rights reserved * * * This software is distributed under the Common Public License 1.0 * */#include "tsk_hashdb_i.h"/** * \file hk_index.c * Contains functions to read and process hash keeper database files *//** * Test the file to see if it is a hashkeeper database * * @param hFile File handle to hash database * * @return 1 if hk and 0 if not */uint8_thk_test(FILE * hFile){ char buf[TSK_HDB_MAXLEN]; int cnt = 0; char *ptr; fseek(hFile, 0, SEEK_SET); if (NULL == fgets(buf, TSK_HDB_MAXLEN, hFile)) return 0; if (strlen(buf) < TSK_HDB_HTYPE_MD5_LEN) return 0; ptr = buf; /* Cycle through the line looking at the fields in between the commas */ while (NULL != (ptr = strchr(ptr, ','))) { cnt++; // run some tets on the MD5 field if (cnt == 4) { /* Do a length check and more sanity checks */ if ((strlen(ptr) < 2 + TSK_HDB_HTYPE_MD5_LEN) || (ptr[1] != '"') || (ptr[2 + TSK_HDB_HTYPE_MD5_LEN] != '"')) { return 0; } if ((isxdigit((int) ptr[2]) == 0) || (isxdigit((int) ptr[2 + TSK_HDB_HTYPE_MD5_LEN - 1]) == 0)) { return 0; } /* Final sanity check */ if (NULL != strchr(ptr, ',')) { return 0; } return 1; } /* If the next field is in quotes then we need to skip to the * next quote and ignore any ',' in there */ if (ptr[1] == '"') { if (NULL == (ptr = strchr(&ptr[2], '"'))) { return 0; } } else { ptr++; } } return 0;}/** * Give a line from a hash keeper database, parse out the * MD5 (and other) text. NOTE that this will add NULL values * to the input text. * * @param str [in] String to parse * @param md5 [out] Pointer to a pointer, which will be assigned to the MD5 text in original string * @param name [in] Poiner to buffer where name can be copied into (can be NULL) * @param n_len [in] Length of name buffer * @param other [in] Pointer to buffer where extended data should be copied to (can be NULL) * @param o_len [in] Length of other buffer */static inthk_parse_md5(char *str, char **md5, char *name, int n_len, char *other, int o_len){ char *ptr = str; char *file = NULL, *dir = NULL, *file_id = NULL, *hash_id = NULL; int cnt = 0; if ((str == NULL) || (strlen(str) < TSK_HDB_HTYPE_MD5_LEN)) return 1; if ((md5 == NULL) && (name == NULL) && (other == NULL)) return 0; /* * 0 file_id * 1 hashset_id * 2 file_name * 3 directory * 4 hash * 5 file_size * 6 date_modified * 7 time modified * 8 time_zone * 9 comments * 10 date_accessed * 11 time_accessed */ /* Assign the file_id if we are looking for it */ if (other != NULL) { file_id = ptr; } while (NULL != (ptr = strchr(ptr, ','))) { cnt++; /* End of file_id, begin hash_id */ if ((cnt == 1) && (other != NULL)) { *ptr = '\0'; ptr++; hash_id = ptr; } /* End of hash_id, begin name */ else if (cnt == 2) { /* Finish the 'other' stuff */ if (other != NULL) { *ptr = '\0'; snprintf(other, o_len, "Hash ID: %s File ID: %s", hash_id, file_id); } /* Are we done? */ if ((name == NULL) && (md5 == NULL)) return 0; /* get the pointer to the name */ if (name) { if (ptr[1] != '"') return 1; file = &ptr[2]; /* We utilize the other loop code to find the end of * the name */ } } /* end of the name, begin directory - which may not exist */ else if ((cnt == 3) && (name != NULL)) { /* finish up the name */ if (ptr[-1] != '"') return 1; ptr[-1] = '\0'; /* get the directory start, if it exists */ if (ptr[1] == '"') { dir = &ptr[2]; } else { dir = NULL; } } /* end of directory, begin MD5 value */ else if (cnt == 4) { /* Copy the name into the buffer */ if (name != NULL) { name[0] = '\0'; if (dir) { /* finish up the dir */ if (ptr[-1] != '"') return 1; ptr[-1] = '\0'; strncpy(name, dir, n_len); strncat(name, "\\", n_len); } if (file) { strncat(name, file, n_len); } else { return 1; } } if (md5 == NULL) return 0; /* Do a length check and more sanity checks */ if ((strlen(ptr) < 2 + TSK_HDB_HTYPE_MD5_LEN) || (ptr[1] != '"') || (ptr[2 + TSK_HDB_HTYPE_MD5_LEN] != '"')) { return 1; } ptr = &ptr[2]; ptr[TSK_HDB_HTYPE_MD5_LEN] = '\0'; *md5 = ptr; /* Final sanity check */ if (NULL != strchr(ptr, ',')) { return 1; } return 0; } /* If the next field is in quotes then we need to skip to the * next quote and ignore any ',' in there */ if (ptr[1] == '"') { if (NULL == (ptr = strchr(&ptr[2], '"'))) { return 1; } } else { ptr++; } } return 1;}/** * Process the database to create a sorted index of it. Consecutive * entries with the same hash value are not added to the index, but * will be found during lookup. * * @param hdb_info Hash database to make index of * @param dbtype Text of database type (should always be TSK_HDB_DBTYPE_HK_STR) * * @return 1 on error and 0 on success. */uint8_thk_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype){ int i; size_t len = 0; char buf[TSK_HDB_MAXLEN]; char *hash = NULL, phash[TSK_HDB_HTYPE_MD5_LEN + 1]; TSK_OFF_T offset = 0; int db_cnt = 0, idx_cnt = 0, ig_cnt = 0; if (tsk_hdb_idxinitialize(hdb_info, dbtype)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hk_makeindex"); return 1; } fseek(hdb_info->hDb, 0, SEEK_SET); /* Status */ if (tsk_verbose) TFPRINTF(stderr, _TSK_T("Extracting Data from Database (%s)\n"), hdb_info->db_fname); /* Allocate a buffer to hold the previous hash values */ memset(phash, '0', TSK_HDB_HTYPE_MD5_LEN + 1); /* read each line of the file */ fseek(hdb_info->hDb, 0, SEEK_SET); for (i = 0; NULL != fgets(buf, TSK_HDB_MAXLEN, hdb_info->hDb); offset += (TSK_OFF_T) len, i++) { len = strlen(buf); /* Parse each line to get the MD5 value */ if (hk_parse_md5(buf, &hash, NULL, 0, NULL, 0)) { ig_cnt++; continue; } db_cnt++; /* If this entry is for the same hash value as the last entry, * the skip it -- we'll look for it during lookup */ if (memcmp(hash, phash, TSK_HDB_HTYPE_MD5_LEN) == 0) { continue; } /* Add the entry to the index */ if (tsk_hdb_idxaddentry(hdb_info, hash, offset)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hk_makeindex"); return 1; } idx_cnt++; /* Set the previous hash value */ strncpy(phash, hash, TSK_HDB_HTYPE_MD5_LEN + 1); } if (idx_cnt > 0) { if (tsk_verbose) { fprintf(stderr, " Valid Database Entries: %d\n", db_cnt); fprintf(stderr, " Invalid Database Entries (headers or errors): %d\n", ig_cnt); fprintf(stderr, " Index File Entries %s: %d\n", (idx_cnt == db_cnt) ? "" : "(optimized)", idx_cnt); } /* Finish the index making process */ if (tsk_hdb_idxfinalize(hdb_info)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hk_makeindex"); return 1; } } else { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_CORRUPT; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_makeindex: No valid entries found in database"); return 1; } return 0;}/** * Find the corresponding name at the * given offset. The offset was likely determined from the index. * The entries in the DB following the one specified are also processed * if they have the same hash value and their name is different. * The callback is called for each entry. * * @param hdb_info Data base to get data from. * @param hash MD5 hash value that was searched for * @param offset Byte offset where hash value should be located in db_file * @param flags * @param action Callback used for each entry found in lookup * @param cb_ptr Pointer to data passed to callback * * @return 1 on error and 0 on success */uint8_thk_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset, TSK_HDB_FLAG_ENUM flags, TSK_HDB_LOOKUP_FN action, void *cb_ptr){ char buf[TSK_HDB_MAXLEN], name[TSK_HDB_MAXLEN], *ptr = NULL, pname[TSK_HDB_MAXLEN], other[TSK_HDB_MAXLEN]; int found = 0; if (tsk_verbose) fprintf(stderr, "hk_getentry: Lookup up hash %s at offset %" PRIuOFF "\n", hash, offset); if (strlen(hash) != TSK_HDB_HTYPE_MD5_LEN) { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Invalid hash value: %s", hash); return 1; } memset(pname, '0', TSK_HDB_MAXLEN); /* Loop so that we can find multiple occurances of the same hash */ while (1) { size_t len; if (0 != fseeko(hdb_info->hDb, offset, SEEK_SET)) { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_READDB; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Error seeking to get file name: %lu", (unsigned long) offset); return 1; } if (NULL == fgets(hdb_info->idx_lbuf, TSK_HDB_MAXLEN, hdb_info->hDb)) { if (feof(hdb_info->hDb)) { break; } tsk_error_reset(); tsk_errno = TSK_ERR_HDB_READDB; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Error reading database"); return 1; } len = strlen(buf); if (len < TSK_HDB_HTYPE_MD5_LEN) { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_CORRUPT; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Invalid entry in database (too short): %s", buf); return 1; } if (hk_parse_md5(buf, &ptr, name, TSK_HDB_MAXLEN, ((flags & TSK_HDB_FLAG_EXT) ? other : NULL), ((flags & TSK_HDB_FLAG_EXT) ? TSK_HDB_MAXLEN : 0))) { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_CORRUPT; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Invalid entry in database: %s", buf); return 1; } /* Is this the one that we want? */ if (0 != strcasecmp(ptr, hash)) { break; } if (strcmp(name, pname) != 0) { int retval; retval = action(hdb_info, hash, name, cb_ptr); if (retval == TSK_WALK_ERROR) { return 1; } else if (retval == TSK_WALK_STOP) { return 0; } //if (flags & FLAG_EXT) // printf("%s\t%s\t(%s)\n", hash, name, other); // else // printf("%s\t%s\n", hash, name); found = 1; strncpy(pname, name, TSK_HDB_MAXLEN); } /* Advance to the next row */ offset += len; } if (found == 0) { tsk_error_reset(); tsk_errno = TSK_ERR_HDB_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "hk_getentry: Hash not found in file at offset: %lu", (unsigned long) offset); return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -