⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntfs_dent.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** ntfs_dent** The Sleuth Kit**** name layer support for the NTFS file system**** 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**** Unicode added with support from I.D.E.A.L. Technology Corp (Aug '05)***/#include "tsk_fs_i.h"#include "tsk_ntfs.h"/** * \file ntfs_dent.c * NTFS file name processing internal functions. *//******************************************************************************** Find an unallocated NTFS MFT entry based on its parent directory*/typedef struct {    TSK_FS_NAME *fs_name;    TSK_INUM_T parinode;    TSK_FS_DIR *fs_dir;} NTFS_PAR_DATA;/* dent call back for tsk_fs_ifind_par to find unallocated files * based on parent directory*/static TSK_WALK_RET_ENUMntfs_par_act(TSK_FS_FILE * fs_file, void *ptr){    NTFS_PAR_DATA *par_data = (NTFS_PAR_DATA *) ptr;    TSK_FS_META_NAME_LIST *fs_name_list;    /* go through each file name structure */    fs_name_list = fs_file->meta->name2;    while (fs_name_list) {        // we got our target        if (fs_name_list->par_inode == par_data->parinode) {            /* Fill in the basics of the fs_name entry              * so we can print in the fls formats */            par_data->fs_name->meta_addr = fs_file->meta->addr;            par_data->fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;            strncpy(par_data->fs_name->name, fs_name_list->name,                par_data->fs_name->name_size);            if (fs_file->meta->type == TSK_FS_META_TYPE_DIR)                par_data->fs_name->type = TSK_FS_NAME_TYPE_DIR;            else                par_data->fs_name->type = TSK_FS_NAME_TYPE_REG;            tsk_fs_dir_add(par_data->fs_dir, par_data->fs_name);        }        fs_name_list = fs_name_list->next;    }    return TSK_WALK_CONT;}static uint8_tntfs_dent_copy(NTFS_INFO * ntfs, ntfs_idxentry * idxe,    TSK_FS_NAME * fs_name){    ntfs_attr_fname *fname = (ntfs_attr_fname *) & idxe->stream;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;    UTF16 *name16;    UTF8 *name8;    int retVal;    int i;    fs_name->meta_addr = tsk_getu48(fs->endian, idxe->file_ref);    fs_name->meta_seq = tsk_getu16(fs->endian, idxe->seq_num);    name16 = (UTF16 *) & fname->name;    name8 = (UTF8 *) fs_name->name;    retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,        (UTF16 *) ((uintptr_t) name16 +            fname->nlen * 2), &name8,        (UTF8 *) ((uintptr_t) name8 +            fs_name->name_size), TSKlenientConversion);    if (retVal != TSKconversionOK) {        *name8 = '\0';        if (tsk_verbose)            tsk_fprintf(stderr,                "Error converting NTFS name to UTF8: %d %" PRIuINUM,                retVal, fs_name->meta_addr);    }    /* Make sure it is NULL Terminated */    if ((uintptr_t) name8 > (uintptr_t) fs_name->name + fs_name->name_size)        fs_name->name[fs_name->name_size] = '\0';    else        *name8 = '\0';    /* Clean up name */    i = 0;    while (fs_name->name[i] != '\0') {        if (TSK_IS_CNTRL(fs_name->name[i]))            fs_name->name[i] = '^';        i++;    }    if (tsk_getu64(fs->endian, fname->flags) & NTFS_FNAME_FLAGS_DIR)        fs_name->type = TSK_FS_NAME_TYPE_DIR;    else        fs_name->type = TSK_FS_NAME_TYPE_REG;    fs_name->flags = 0;    return 0;}/* This is a sanity check to see if the time is valid * it is divided by 100 to keep it in a 32-bit integer  */static uint8_tis_time(uint64_t t){#define SEC_BTWN_1601_1970_DIV100 ((369*365 + 89) * 24 * 36)#define SEC_BTWN_1601_2010_DIV100 (SEC_BTWN_1601_1970_DIV100 + (40*365 + 6) * 24 * 36)    t /= 1000000000;            /* put the time in seconds div by additional 100 */    if (!t)        return 0;    if (t < SEC_BTWN_1601_1970_DIV100)        return 0;    if (t > SEC_BTWN_1601_2010_DIV100)        return 0;    return 1;}/**  * Process a lsit of index entries and add to FS_DIR * * @param a_is_del Set to 1 if these entries are for a deleted directory * @param idxe Buffer with index entries to process * @param idxe_len Length of idxe buffer (in bytes) * @param used_len Length of data as reported by idexlist header (everything * after which and less then idxe_len is considered deleted) * * @returns 1 to stop, 0 on success, and -1 on error */// @@@ Should make a_idxe const and use internal pointer in function loopstatic TSK_RETVAL_ENUMntfs_proc_idxentry(NTFS_INFO * a_ntfs, TSK_FS_DIR * a_fs_dir,    uint8_t a_is_del, ntfs_idxentry * a_idxe, uint32_t a_idxe_len,    uint32_t a_used_len){    uintptr_t endaddr, endaddr_alloc;    TSK_FS_NAME *fs_name;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & a_ntfs->fs_info;    if ((fs_name = tsk_fs_name_alloc(NTFS_MAXNAMLEN_UTF8, 0)) == NULL) {        return TSK_ERR;    }    if (tsk_verbose)        tsk_fprintf(stderr,            "ntfs_proc_idxentry: Processing index entry: %" PRIu64            "  Size: %" PRIu32 "  Len: %" PRIu32 "\n",            (uint64_t) ((uintptr_t) a_idxe), a_idxe_len, a_used_len);    /* Sanity check */    if (a_idxe_len < a_used_len) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "ntfs_proc_idxentry: Allocated length of index entries is larger than buffer length");        return TSK_ERR;    }    /* where is the end of the buffer */    endaddr = ((uintptr_t) a_idxe + a_idxe_len);    /* where is the end of the allocated data */    endaddr_alloc = ((uintptr_t) a_idxe + a_used_len);    /* cycle through the index entries, based on provided size */    while (((uintptr_t) & (a_idxe->stream) + sizeof(ntfs_attr_fname)) <        endaddr) {        ntfs_attr_fname *fname = (ntfs_attr_fname *) & a_idxe->stream;        if (tsk_verbose)            tsk_fprintf(stderr,                "ntfs_proc_idxentry: New IdxEnt: %" PRIu64                " $FILE_NAME Entry: %" PRIu64 "  File Ref: %" PRIu64                "  IdxEnt Len: %" PRIu16 "  StrLen: %" PRIu16 "\n",                (uint64_t) ((uintptr_t) a_idxe),                (uint64_t) ((uintptr_t) fname),                (uint64_t) tsk_getu48(fs->endian, a_idxe->file_ref),                tsk_getu16(fs->endian, a_idxe->idxlen),                tsk_getu16(fs->endian, a_idxe->strlen));        /* perform some sanity checks on index buffer head         * and advance by 4-bytes if invalid         */        if ((tsk_getu48(fs->endian, a_idxe->file_ref) > fs->last_inum) ||            (tsk_getu48(fs->endian, a_idxe->file_ref) < fs->first_inum) ||            (tsk_getu16(fs->endian,                    a_idxe->idxlen) <= tsk_getu16(fs->endian,                    a_idxe->strlen))            || (tsk_getu16(fs->endian, a_idxe->idxlen) % 4)            || (tsk_getu16(fs->endian, a_idxe->idxlen) > a_idxe_len)) {            a_idxe = (ntfs_idxentry *) ((uintptr_t) a_idxe + 4);            continue;        }        /* do some sanity checks on the deleted entries         */        if ((tsk_getu16(fs->endian, a_idxe->strlen) == 0) ||            (((uintptr_t) a_idxe + tsk_getu16(fs->endian,                        a_idxe->idxlen)) > endaddr_alloc)) {            /* name space checks */            if ((fname->nspace != NTFS_FNAME_POSIX) &&                (fname->nspace != NTFS_FNAME_WIN32) &&                (fname->nspace != NTFS_FNAME_DOS) &&                (fname->nspace != NTFS_FNAME_WINDOS)) {                a_idxe = (ntfs_idxentry *) ((uintptr_t) a_idxe + 4);                if (tsk_verbose)                    tsk_fprintf(stderr,                        "ntfs_proc_idxentry: Skipping because of invalid name space\n");                continue;            }            if ((tsk_getu64(fs->endian, fname->alloc_fsize) <                    tsk_getu64(fs->endian, fname->real_fsize))                || (fname->nlen == 0)                || (*(uint8_t *) & fname->name == 0)) {                a_idxe = (ntfs_idxentry *) ((uintptr_t) a_idxe + 4);                if (tsk_verbose)                    tsk_fprintf(stderr,                        "ntfs_proc_idxentry: Skipping because of reported file sizes, name length, or NULL name\n");                continue;            }            if ((is_time(tsk_getu64(fs->endian, fname->crtime)) == 0) ||                (is_time(tsk_getu64(fs->endian, fname->atime)) == 0) ||                (is_time(tsk_getu64(fs->endian, fname->mtime)) == 0)) {                a_idxe = (ntfs_idxentry *) ((uintptr_t) a_idxe + 4);                if (tsk_verbose)                    tsk_fprintf(stderr,                        "ntfs_proc_idxentry: Skipping because of invalid times\n");                continue;            }        }        /* For all fname entries, there will exist a DOS style 8.3          * entry.  We don't process those because we already processed         * them before in their full version.  If the type is          * full POSIX or WIN32 that does not satisfy DOS, then a          * type NTFS_FNAME_DOS will exist.  If the name is WIN32,         * but already satisfies DOS, then a type NTFS_FNAME_WINDOS         * will exist          *         * Note that we could be missing some info from deleted files         * if the windows version was deleted and the DOS wasn't...         *         * @@@ This should be added to the shrt_name entry of TSK_FS_NAME.  The short         * name entry typically comes after the long name         */        if (fname->nspace == NTFS_FNAME_DOS) {            if (tsk_verbose)                tsk_fprintf(stderr,                    "ntfs_proc_idxentry: Skipping because of name space: %d\n",                    fname->nspace);            goto incr_entry;        }        /* Copy it into the generic form */        if (ntfs_dent_copy(a_ntfs, a_idxe, fs_name)) {            if (tsk_verbose)                tsk_fprintf(stderr,                    "ntfs_proc_idxentry: Skipping because error copying dent_entry\n");            goto incr_entry;        }        /*          * Check if this entry is deleted         *         * The final check is to see if the end of this entry is          * within the space that the idxallocbuf claimed was valid OR         * if the parent directory is deleted         */        if ((a_is_del == 1) ||            (tsk_getu16(fs->endian, a_idxe->strlen) == 0) ||            (((uintptr_t) a_idxe + tsk_getu16(fs->endian,                        a_idxe->idxlen)) > endaddr_alloc)) {            fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;        }        else {            fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;        }        if (tsk_verbose)            tsk_fprintf(stderr,                "ntfs_proc_idxentry: Entry Details of %s: Str Len: %"                PRIu16 "  Len to end after current: %" PRIu64                "  flags: %x\n", fs_name->name, tsk_getu16(fs->endian,                    a_idxe->strlen),                (uint64_t) (endaddr_alloc - (uintptr_t) a_idxe -                    tsk_getu16(fs->endian, a_idxe->idxlen)),                fs_name->flags);        if (tsk_fs_dir_add(a_fs_dir, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }      incr_entry:        /* the theory here is that deleted entries have strlen == 0 and         * have been found to have idxlen == 16         *         * if the strlen is 0, then guess how much the indexlen was         * before it was deleted         */        /* 16: size of idxentry before stream         * 66: size of fname before name         * 2*nlen: size of name (in unicode)         */        if (tsk_getu16(fs->endian, a_idxe->strlen) == 0) {            a_idxe =                (ntfs_idxentry                *) ((((uintptr_t) a_idxe + 16 + 66 + 2 * fname->nlen +                        3) / 4) * 4);        }        else {            a_idxe =                (ntfs_idxentry *) ((uintptr_t) a_idxe +                tsk_getu16(fs->endian, a_idxe->idxlen));        }    }                           /* end of loop of index entries */    tsk_fs_name_free(fs_name);    return TSK_OK;}/* * remove the update sequence values that are changed in the last two  * bytes of each sector  * * return 1 on error and 0 on success */static uint8_tntfs_fix_idxrec(NTFS_INFO * ntfs, ntfs_idxrec * idxrec, uint32_t len){    int i;    uint16_t orig_seq;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;    ntfs_upd *upd;    if (tsk_verbose)        tsk_fprintf(stderr,            "ntfs_fix_idxrec: Fixing idxrec: %" PRIu64 "  Len: %"            PRIu32 "\n", (uint64_t) ((uintptr_t) idxrec), len);    /* sanity check so we don't run over in the next loop */    if ((unsigned int) ((tsk_getu16(fs->endian, idxrec->upd_cnt) - 1) *            ntfs->ssize_b) > len) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fix_idxrec: More Update Sequence Entries than idx record size");        return 1;    }    /* Apply the update sequence structure template */    upd =        (ntfs_upd *) ((uintptr_t) idxrec + tsk_getu16(fs->endian,            idxrec->upd_off));    /* Get the sequence value that each 16-bit value should be */    orig_seq = tsk_getu16(fs->endian, upd->upd_val);    /* cycle through each sector */    for (i = 1; i < tsk_getu16(fs->endian, idxrec->upd_cnt); i++) {        /* The offset into the buffer of the value to analyze */        int offset = i * ntfs->ssize_b - 2;        uint8_t *new_val, *old_val;        /* get the current sequence value */        uint16_t cur_seq =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -