📄 fs_attr.c
字号:
/*** fs_attr** The Sleuth Kit **** Brian Carrier [carrier <at> sleuthkit [dot] org]** Copyright (c) 2006-2008 Brian Carrier, Basis Technology. All Rights reserved** Copyright (c) 2003-2005 Brian Carrier. All rights reserved **** TASK** Copyright (c) 2002 Brian Carrier, @stake Inc. All rights reserved****** This software is distributed under the Common Public License 1.0***//** * \file fs_attr.c * Functions to allocate and add structures to maintain generic file * system attributes and run lists. *//* * The TSK_FS_ATTR structure is motivated by NTFS. NTFS (and others) allow * one to have more than one data area per file. Furthermore, there is * more than one way to store the data (resident in the MFT entry or * in the Data Area runs). To handle this in * a generic format, the TSK_FS_ATTR structure was created. * * TSK_FS_ATTR structures have a type and id that describe it and then * a flag identifies it as a resident stream or a non-resident run * They form a linked list and are added to the TSK_FS_META structure */#include "tsk_fs_i.h"/** * \internal * Allocate a run list entry. * * @returns NULL on error */TSK_FS_ATTR_RUN *tsk_fs_attr_run_alloc(){ TSK_FS_ATTR_RUN *fs_attr_run = (TSK_FS_ATTR_RUN *) tsk_malloc(sizeof(TSK_FS_ATTR_RUN)); if (fs_attr_run == NULL) return NULL; return fs_attr_run;}/** * \internal * Free a list of data_runs * * @param fs_attr_run Head of list to free */voidtsk_fs_attr_run_free(TSK_FS_ATTR_RUN * fs_attr_run){ TSK_FS_ATTR_RUN *fs_attr_run_prev; while (fs_attr_run) { fs_attr_run_prev = fs_attr_run; fs_attr_run = fs_attr_run->next; fs_attr_run_prev->next = NULL; free(fs_attr_run_prev); }}/** * \internal * Allocates and initializes a new structure. * * @param type The type of attribute to create (Resident or Non-resident) * @returns NULL on error */TSK_FS_ATTR *tsk_fs_attr_alloc(TSK_FS_ATTR_FLAG_ENUM type){ TSK_FS_ATTR *fs_attr = (TSK_FS_ATTR *) tsk_malloc(sizeof(TSK_FS_ATTR)); if (fs_attr == NULL) { return NULL; } fs_attr->name_size = 128; if ((fs_attr->name = (char *) tsk_malloc(fs_attr->name_size)) == NULL) { free(fs_attr); return NULL; } if (type == TSK_FS_ATTR_NONRES) { fs_attr->flags = (TSK_FS_ATTR_NONRES | TSK_FS_ATTR_INUSE); } else if (type == TSK_FS_ATTR_RES) { fs_attr->rd.buf_size = 1024; fs_attr->rd.buf = (uint8_t *) tsk_malloc(fs_attr->rd.buf_size); if (fs_attr->rd.buf == NULL) { free(fs_attr->name); return NULL; } fs_attr->flags = (TSK_FS_ATTR_RES | TSK_FS_ATTR_INUSE); } else { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_attr_alloc: Invalid Type: %d\n", type); return NULL; } return fs_attr;}/** * \internal * Free a single TSK_FS_ATTR structure. This does not free the linked list. * * @param a_fs_attr Structure to free. */voidtsk_fs_attr_free(TSK_FS_ATTR * a_fs_attr){ if (a_fs_attr == NULL) return; if (a_fs_attr->nrd.run) tsk_fs_attr_run_free(a_fs_attr->nrd.run); a_fs_attr->nrd.run = NULL; if (a_fs_attr->rd.buf) free(a_fs_attr->rd.buf); a_fs_attr->rd.buf = NULL; if (a_fs_attr->name) free(a_fs_attr->name); a_fs_attr->name = NULL; free(a_fs_attr);}/** * \internal * Clear the run_lists fields of a single FS_DATA structure * * @param a_fs_attr Structure to clear for reuse */voidtsk_fs_attr_clear(TSK_FS_ATTR * a_fs_attr){ a_fs_attr->size = a_fs_attr->type = a_fs_attr->id = a_fs_attr->flags = 0; if (a_fs_attr->nrd.run) { tsk_fs_attr_run_free(a_fs_attr->nrd.run); a_fs_attr->nrd.run = NULL; a_fs_attr->nrd.run_end = NULL; a_fs_attr->nrd.allocsize = 0; a_fs_attr->nrd.initsize = 0; }}/** * Add a name to an existing FS_DATA structure. Will reallocate * space for the name if needed. * * @param fs_attr Structure to add name to * @param name UTF-8 name to add * * @return 1 on error and 0 on success */static uint8_tfs_attr_put_name(TSK_FS_ATTR * fs_attr, const char *name){ if (name == NULL) { if (fs_attr->name_size > 0) { fs_attr->name[0] = '\0'; } return 0; } if (fs_attr->name_size < (strlen(name) + 1)) { fs_attr->name = tsk_realloc(fs_attr->name, strlen(name) + 1); if (fs_attr->name == NULL) return 1; fs_attr->name_size = strlen(name) + 1; } strncpy(fs_attr->name, name, fs_attr->name_size); return 0;}/** * \internal * Copy resident data to an attribute. * * @param a_fs_attr Attribute to add data to (cannot be NULL) * @param name Name of the attribute to set * @param type Type of the attribute to set * @param id Id of the attribute to set * @param res_data Pointer to where resident data is located (data will * be copied from here into FS_DATA) * @param len Length of resident data * @return 1 on error and 0 on success */uint8_ttsk_fs_attr_set_str(TSK_FS_FILE * a_fs_file, TSK_FS_ATTR * a_fs_attr, const char *name, TSK_FS_ATTR_TYPE_ENUM type, uint16_t id, void *res_data, size_t len){ if (a_fs_attr == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "Null fs_attr in tsk_fs_attr_set_str"); return 1; } a_fs_attr->fs_file = a_fs_file; a_fs_attr->flags = (TSK_FS_ATTR_INUSE | TSK_FS_ATTR_RES); a_fs_attr->type = type; a_fs_attr->id = id; a_fs_attr->nrd.compsize = 0; if (fs_attr_put_name(a_fs_attr, name)) { return 1; } if (a_fs_attr->rd.buf_size < len) { a_fs_attr->rd.buf = (uint8_t *) tsk_realloc((char *) a_fs_attr->rd.buf, len); if (a_fs_attr->rd.buf == NULL) return 1; a_fs_attr->rd.buf_size = len; } memset(a_fs_attr->rd.buf, 0, a_fs_attr->rd.buf_size); memcpy(a_fs_attr->rd.buf, res_data, len); a_fs_attr->size = len; return 0;}/** * \internal * Set the needed fields along with an initial run list for a data attribute. To add more * runs, use ...._add_run(). * * @param a_fs File system the run comes from. * @param a_fs_attr The data attribute to initialize and add the run to * @param a_data_run_new The set of runs to add (can be NULL). * @param name Name of the attribute (can be NULL) * @param type Type of attribute to add run to * @param id Id of attribute to add run to * @param size Total size of the attribute (can be larger than length of initial run being added) * @param alloc_size Allocated size of the attribute (>= size). Identifies the slack space. * @param flags Flags about compression, sparse etc. of data * @param compsize Compression unit size (in case it needs to be created) * * @returns 1 on error and 0 on success */uint8_ttsk_fs_attr_set_run(TSK_FS_FILE * a_fs_file, TSK_FS_ATTR * a_fs_attr, TSK_FS_ATTR_RUN * a_data_run_new, const char *name, TSK_FS_ATTR_TYPE_ENUM type, uint16_t id, TSK_OFF_T size, TSK_OFF_T alloc_size, TSK_FS_ATTR_FLAG_ENUM flags, uint32_t compsize){ TSK_FS_INFO *fs; if ((a_fs_file == NULL) || (a_fs_file->meta == NULL)) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "Null fs_file in tsk_fs_attr_set_run"); return 1; } if (a_fs_attr == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "Null fs_attr in tsk_fs_attr_set_run"); return 1; } fs = a_fs_file->fs_info; if (alloc_size < size) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_attr_set_run: alloc_size (%" PRIuOFF ") is less than size (%" PRIuOFF ")", alloc_size, size); return 1; } a_fs_attr->fs_file = a_fs_file; a_fs_attr->flags = (TSK_FS_ATTR_INUSE | TSK_FS_ATTR_NONRES | flags); a_fs_attr->type = type; a_fs_attr->id = id; a_fs_attr->size = size; a_fs_attr->nrd.allocsize = alloc_size; a_fs_attr->nrd.initsize = 0; a_fs_attr->nrd.compsize = compsize; if (fs_attr_put_name(a_fs_attr, name)) { return 1; } /* Add the a_data_run_new to the attribute. */ /* We support the ODD case where the run is NULL. In this case, * we set the attribute size info, but set everything else to NULL. */ if (a_data_run_new == NULL) { a_fs_attr->nrd.run = NULL; a_fs_attr->nrd.run_end = NULL; return 0; } /* * If this is not in the begining, then we need to make a filler * to account for the cluster numbers we haven't seen yet * * This commonly happens when we process an MFT entry that * is not a base entry and it is referenced in an $ATTR_LIST * * The $DATA attribute in the non-base have a non-zero * a_data_run_new->offset. */ if (a_data_run_new->offset != 0) { TSK_FS_ATTR_RUN *fill_run = tsk_fs_attr_run_alloc(); fill_run->flags = TSK_FS_ATTR_RUN_FLAG_FILLER; fill_run->offset = 0; fill_run->addr = 0; fill_run->len = a_data_run_new->offset; fill_run->next = a_data_run_new; a_data_run_new = fill_run; } a_fs_attr->nrd.run = a_data_run_new; // update the pointer to the end of the list and the initsize a_fs_attr->nrd.run_end = a_data_run_new; a_fs_attr->nrd.initsize = (a_fs_attr->nrd.run_end->len * fs->block_size); while (a_fs_attr->nrd.run_end->next) { a_fs_attr->nrd.run_end = a_fs_attr->nrd.run_end->next; a_fs_attr->nrd.initsize += (a_fs_attr->nrd.run_end->len * fs->block_size); } return 0;}/** * \internal * Add a set of consecutive runs to an attribute. This will add and remove FILLER entries * as needed and update internal variables. * * @param a_fs File system run is from * @param fs_attr Attribute to add run to * @param a_data_run_new The set of runs to add. * * @returns 1 on error and 0 on succes */uint8_ttsk_fs_attr_add_run(TSK_FS_INFO * a_fs, TSK_FS_ATTR * a_fs_attr, TSK_FS_ATTR_RUN * a_data_run_new){ TSK_FS_ATTR_RUN *data_run_cur, *data_run_prev; TSK_DADDR_T run_len; tsk_error_reset(); if (a_fs_attr == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -