Пример #1
0
static uint8_t
ntfs_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;
}
Пример #2
0
/*
 * Inspects a byte address for an XTAF superblock structure.
 *
 * @param offset Offset in sectors.
 *
 * Returns 0 on finding a sane-looking XTAF superblock.
 * Returns 1 on finding non-XTAF-superblock data.
 * Returns <0 on more basic errors (memory, I/O).
 */
int
tsk_vs_xtaf_verifysb(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, unsigned int sector_size){
    ssize_t cnt;
    xtaffs_sb* xtafsb;
    unsigned int xtafsb_len;

    xtafsb_len = sizeof(xtaffs_sb);

    /* Allocate superblock struct. */
    xtafsb = (xtaffs_sb*) tsk_malloc(xtafsb_len);
    if (NULL == xtafsb) {
        tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Failed to allocate superblock for partition %d.\n");
        free(xtafsb);
        return -ENOMEM;
    }

    /* Read in superblock. */
    /* NOTE: This is read as a char* instead of a xtaffs_sb to keep img_read() happy. */
    cnt = tsk_img_read(img_info, offset, (char *) xtafsb, xtafsb_len);
    /* Check for a failed read. */
    if (cnt != xtafsb_len) {
        tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Failed to read at disk offset %" PRIuDADDR " bytes.\n", offset * sector_size);
        free(xtafsb);
        return -EIO;
    }

    /* Sanity test: Check the magic. */
    if(strncmp((char*) xtafsb->magic, "XTAF", 4)){
        if (tsk_verbose)
            tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Partition at %" PRIuDADDR " bytes is not an XTAF file system.\n", offset * sector_size);
        free(xtafsb);
        return 1;
    }

    /* The partition at this point is sane. No further need to check the superblock. */
    free(xtafsb);

    return 0;
}
Пример #3
0
/* Used to process orphan directories and make sure that their contents
 * are now marked as reachable */
static TSK_WALK_RET_ENUM
load_orphan_dir_walk_cb(TSK_FS_FILE * a_fs_file, const char *a_path,
    void *a_ptr)
{
    FIND_ORPHAN_DATA *data = (FIND_ORPHAN_DATA *) a_ptr;

    // ignore DOT entries
    if ((a_fs_file->name) && (a_fs_file->name->name) &&
        (TSK_FS_ISDOT(a_fs_file->name->name)))
        return TSK_WALK_CONT;

    // add this entry to the orphan list
    if (a_fs_file->meta) {
        /* Stop if we hit an allocated entry.  We shouldn't get these, but did
         * have some trouble images that went into allocated clusters on
         * a FAT file system. */
        if (a_fs_file->meta->flags & TSK_FS_META_FLAG_ALLOC) {
            if (tsk_verbose) {
                tsk_fprintf(stderr,
                    "load_orphan_dir_walk_cb: Skipping an allocated file (ID: %"
                    PRIuINUM ")\n", a_fs_file->meta->addr);
            }
            return TSK_WALK_STOP;
        }

        /* check if we have already added it as an orphan (in a subdirectory)
         * Not entirely sure how possible this is, but it was added while
         * debugging an infinite loop problem. */
        if (tsk_list_find(data->orphan_subdir_list, a_fs_file->meta->addr)) {
            if (tsk_verbose)
                fprintf(stderr,
                    "load_orphan_dir_walk_cb: Detected loop with address %"
                    PRIuINUM, a_fs_file->meta->addr);
            return TSK_WALK_STOP;
        }

        tsk_list_add(&data->orphan_subdir_list, a_fs_file->meta->addr);

        /* FAT file systems spend a lot of time hunting for parent
         * directory addresses, so we put this code in here to save
         * the info when we have it. */
        if ((a_fs_file->meta->type == TSK_FS_META_TYPE_DIR)
            && (TSK_FS_TYPE_ISFAT(a_fs_file->fs_info->ftype))) {
            if (fatfs_dir_buf_add((FATFS_INFO *) a_fs_file->fs_info,
                    a_fs_file->name->par_addr, a_fs_file->meta->addr))
                return TSK_WALK_ERROR;
        }
    }

    return TSK_WALK_CONT;
}
Пример #4
0
/*
 * Parse the UsnJrnl record.
 * Calls the action callback.
 * Returns TSK_WALK_CONT on success, TSK_WALK_ERROR on error.
 */
static TSK_WALK_RET_ENUM
parse_record(const unsigned char *buf, TSK_USN_RECORD_HEADER *header,
             TSK_ENDIAN_ENUM endian, TSK_FS_USNJENTRY_WALK_CB action, void *ptr)
{
    TSK_WALK_RET_ENUM ret;

    switch (header->major_version) {
    case 2: {
        TSK_USN_RECORD_V2 record;

        ret = parse_v2_record(buf, header, &record, endian);
        if (ret == 1)
            return TSK_WALK_ERROR;

        ret = (*action)(header, &record, ptr);

        free(record.fname);

        return ret;
    }
    case 3: {
        if (tsk_verbose)
            tsk_fprintf(stderr,
                        "parse_record: USN records V 3 not supported yet.");

        return TSK_WALK_CONT;
    }
    case 4: {
        if (tsk_verbose)
            tsk_fprintf(stderr,
                        "parse_record: USN records V 4 not supported yet.");

        return TSK_WALK_CONT;
    }
    default: return TSK_WALK_ERROR;
    }
}
Пример #5
0
/* Place journal data in *fs
 *
 * Return 0 on success and 1 on error 
 * */
uint8_t
ext2fs_jopen(TSK_FS_INFO * fs, TSK_INUM_T inum)
{
    EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) fs;
    EXT2FS_JINFO *jinfo;

    // clean up any error messages that are lying around
    tsk_error_reset();

    if (!fs) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "ext2fs_jopen: fs is null");
        return 1;
    }

    ext2fs->jinfo = jinfo =
        (EXT2FS_JINFO *) tsk_malloc(sizeof(EXT2FS_JINFO));
    if (jinfo == NULL) {
        return 1;
    }
    jinfo->j_inum = inum;

    jinfo->fs_file = tsk_fs_file_open_meta(fs, NULL, inum);
    if (!jinfo->fs_file) {
        free(jinfo);
        return 1;
//      error("error finding journal inode %" PRIu32, inum);
    }

    if (tsk_fs_file_walk(jinfo->fs_file, 0, load_sb_action, NULL)) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_FWALK;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "Error loading ext3 journal");
        tsk_fs_file_close(jinfo->fs_file);
        free(jinfo);
        return 1;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "journal opened at inode %" PRIuINUM " bsize: %" PRIu32
            " First JBlk: %" PRIuDADDR " Last JBlk: %" PRIuDADDR "\n",
            inum, jinfo->bsize, jinfo->first_block, jinfo->last_block);

    return 0;
}
Пример #6
0
/* print_block - write data block to stdout */
static TSK_WALK_RET_ENUM
print_block(TSK_FS_INFO * fs, TSK_DADDR_T addr, char *buf,
    TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr)
{
    if (tsk_verbose)
        tsk_fprintf(stderr, "write block %" PRIuDADDR "\n", addr);

    if (fwrite(buf, fs->block_size, 1, stdout) != 1) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_WRITE;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "dls_lib: error writing to stdout: %s", strerror(errno));
        return TSK_WALK_ERROR;
    }

    return TSK_WALK_CONT;
}
Пример #7
0
/* print_block - write data block to stdout */
static TSK_WALK_RET_ENUM
print_block(const TSK_FS_BLOCK * fs_block, void *ptr)
{
    if (tsk_verbose)
        tsk_fprintf(stderr, "write block %" PRIuDADDR "\n",
            fs_block->addr);

    if (fwrite(fs_block->buf, fs_block->fs_info->block_size, 1,
            stdout) != 1) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WRITE);
        tsk_error_set_errstr("blkls_lib: error writing to stdout: %s",
            strerror(errno));
        return TSK_WALK_ERROR;
    }

    return TSK_WALK_CONT;
}
Пример #8
0
static void
usage()
{
    fprintf(stderr,
        "usage: %s [-vV] [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] image [images]\n",
        progname);
    fprintf(stderr, "\t-i imgtype: The format of the image file\n");
    tsk_fprintf(stderr,
        "\t-b dev_sector_size: The size (in bytes) of the device sectors\n");
    fprintf(stderr,
        "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
    fprintf(stderr, "\t-v: verbose output to stderr\n");
    fprintf(stderr, "\t-V: Print version\n");
    fprintf(stderr, "\t-f fstype: File system type\n");
    fs_print_types(stderr);
    img_print_types(stderr);

    exit(1);
}
Пример #9
0
static TSK_WALK_RET_ENUM
slack_file_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off, TSK_DADDR_T addr,
    char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr)
{
    BLKLS_DATA *data = (BLKLS_DATA *) ptr;

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "slack_file_act: File: %" PRIuINUM " Remaining File:  %"
            PRIuOFF "  Buffer: %u\n", fs_file->meta->addr, data->flen,
            size);

    /* This is not the last data unit */
    if (data->flen >= size) {
        data->flen -= size;
    }
    /* We have passed the end of the allocated space */
    else if (data->flen == 0) {
        if (fwrite(buf, size, 1, stdout) != 1) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_FS_WRITE);
            tsk_error_set_errstr("blkls_lib: error writing to stdout: %s",
                strerror(errno));
            return TSK_WALK_ERROR;
        }
    }
    /* This is the last data unit and there is unused space */
    else if (data->flen < size) {
        /* Clear the used space and print it */
        memset(buf, 0, (size_t) data->flen);
        if (fwrite(buf, size, 1, stdout) != 1) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_FS_WRITE);
            tsk_error_set_errstr("blkls_lib: error writing to stdout: %s",
                strerror(errno));
            return TSK_WALK_ERROR;
        }
        data->flen = 0;
    }

    return TSK_WALK_CONT;
}
Пример #10
0
/*
** find_inode
**
** Callback action for inode_walk
*/
static TSK_WALK_RET_ENUM
ifind_data_act(TSK_FS_FILE * fs_file, void *ptr)
{
    IFIND_DATA_DATA *data = (IFIND_DATA_DATA *) ptr;
    int file_flags =
        (TSK_FS_FILE_WALK_FLAG_AONLY | TSK_FS_FILE_WALK_FLAG_SLACK);
    int i, cnt;

    data->curinode = fs_file->meta->addr;

    /* Search all attributes */
    cnt = tsk_fs_file_attr_getsize(fs_file);
    for (i = 0; i < cnt; i++) {
        const TSK_FS_ATTR *fs_attr = tsk_fs_file_attr_get_idx(fs_file, i);
        if (!fs_attr)
            continue;

        data->curtype = fs_attr->type;
        data->curid = fs_attr->id;
        if (fs_attr->flags & TSK_FS_ATTR_NONRES) {
            if (tsk_fs_attr_walk(fs_attr,
                    file_flags, ifind_data_file_act, ptr)) {
                if (tsk_verbose)
                    tsk_fprintf(stderr,
                        "Error walking file %" PRIuINUM
                        " Attribute: %i", fs_file->meta->addr, i);

                /* Ignore these errors */
                tsk_error_reset();
            }

            // stop if we only want one hit
            if ((data->found) && (!(data->flags & TSK_FS_IFIND_ALL)))
                break;
        }
    }

    if ((data->found) && (!(data->flags & TSK_FS_IFIND_ALL)))
        return TSK_WALK_STOP;
    else
        return TSK_WALK_CONT;
}
Пример #11
0
/* usage - explain and terminate */
static void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("usage: %s [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] [-vV] image [images] [inode] blk\n"),
        progname);
    tsk_fprintf(stderr, "\tblk: The journal block to view\n");
    tsk_fprintf(stderr,
        "\tinode: The file system inode where the journal is located\n");
    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-f fstype: File system type (use '-f list' for supported types)\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
    tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: print version\n");
    exit(1);
}
Пример #12
0
/**
* \ingroup fslib
 * Process a specific attribute in a file and call a callback function with the file contents. The callback will be 
 * called with chunks of data that are fs->block_size or less.  The address given in the callback
 * will be correct only for raw files (when the raw file contents were stored in the block).  For
 * compressed and sparse files, the address may be zero. If the file system you are analyzing does
 * not have multiple attributes per file, then you can use tsk_fs_file_walk().  For incomplete or 
 * corrupt files, some missing runs will be identified as SPARSE and zeros will be returned in the content.
 *
 * @param a_fs_file File to process
 * @param a_type Attribute type to process
 * @param a_id Id if attribute to process 
 * @param a_flags Flags to use while processing file
 * @param a_action Callback action to call with content
 * @param a_ptr Pointer that will passed to callback
 * @returns 1 on error and 0 on success.
 */
uint8_t
tsk_fs_file_walk_type(TSK_FS_FILE * a_fs_file,
    TSK_FS_ATTR_TYPE_ENUM a_type, uint16_t a_id,
    TSK_FS_FILE_WALK_FLAG_ENUM a_flags, TSK_FS_FILE_WALK_CB a_action,
    void *a_ptr)
{
    const TSK_FS_ATTR *fs_attr;
    TSK_FS_INFO *fs;

    // clean up any error messages that are lying around
    tsk_error_reset();

    // check the FS_INFO, FS_FILE structures
    if ((a_fs_file == NULL) || (a_fs_file->meta == NULL)
        || (a_fs_file->fs_info == NULL)) {
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "tsk_fs_file_walk: called with NULL pointers");
        return 1;
    }
    else if ((a_fs_file->fs_info->tag != TSK_FS_INFO_TAG)
        || (a_fs_file->meta->tag != TSK_FS_META_TAG)) {
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "tsk_fs_file_walk: called with unallocated structures");
        return 1;
    }
    fs = a_fs_file->fs_info;

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "tsk_fs_file_walk: Processing file %" PRIuINUM "\n",
            a_fs_file->meta->addr);

    if ((fs_attr =
            tsk_fs_file_attr_get_type(a_fs_file, a_type, a_id,
                (a_flags & TSK_FS_FILE_WALK_FLAG_NOID) ? 0 : 1)) == NULL)
        return 1;

    return tsk_fs_attr_walk(fs_attr, a_flags, a_action, a_ptr);
}
Пример #13
0
/* usage - explain and terminate */
static void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("usage: %s [-b num] [-f fstype] [-i imgtype] [-o imgoffset] [-z zone] [-s seconds] [-vV] image inum\n"),
        progname);
    tsk_fprintf(stderr,
        "\t-b num: force the display of NUM address of block pointers\n");
    tsk_fprintf(stderr,
        "\t-z zone: time zone of original machine (i.e. EST5EDT or GMT)\n");
    tsk_fprintf(stderr,
        "\t-s seconds: Time skew of original machine (in seconds)\n");
    tsk_fprintf(stderr,
        "\t-i imgtype: The format of the image file (use '-i list' for supported types)\n");
    tsk_fprintf(stderr,
        "\t-f fstype: File system type (use '-f list' for supported types)\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
    tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: print version\n");
    exit(1);
}
Пример #14
0
static int
tsk_printf_conv(WCHAR * wbuf, int wlen, const char *msg, va_list * args)
{
    char *cbuf;
    UTF8 *ptr8;
    UTF16 *ptr16;
    int retVal;
    size_t len, clen;

    wbuf[0] = '\0';

    /* Allocate a UTF-8 buffer and process the printf args */
    clen = wlen * 3;
    if (NULL == (cbuf = (char *) tsk_malloc(clen))) {
        return 1;
    }
    memset(cbuf, 0, clen);
#ifdef _MSC_VER
    vsnprintf_s(cbuf, clen - 1, _TRUNCATE, msg, *args);
#else
    vsnprintf(cbuf, clen - 1, msg, *args);
#endif
    len = strlen(cbuf);

    //Convert to UTF-16
    ptr8 = (UTF8 *) cbuf;
    ptr16 = (UTF16 *) wbuf;
    retVal =
        tsk_UTF8toUTF16((const UTF8 **) &ptr8, &ptr8[len + 1], &ptr16,
        &ptr16[wlen], TSKlenientConversion);
    if (retVal != TSKconversionOK) {
        *ptr16 = '\0';
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "tsk_printf_conv: error converting string to UTF-16\n");
    }

    free(cbuf);
    return 0;
}
Пример #15
0
void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("%s [-i imgtype] [-o imgoffset] [-brvV] [-t mmtype] image [images]\n"),
        progname);
    tsk_fprintf(stderr,
        "\t-t mmtype: The type of partition system (use '-t list' for list of supported types)\n");
    tsk_fprintf(stderr,
        "\t-i imgtype: The format of the image file (use '-i list' for list supported types)\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: Offset to the start of the volume that contains the partition system (in sectors)\n");
    tsk_fprintf(stderr, "\t-b: print the rounded length in bytes\n");
    tsk_fprintf(stderr,
        "\t-r: recurse and look for other partition tables in partitions (DOS Only)\n");
    tsk_fprintf(stderr, "\t-v: verbose output\n");
    tsk_fprintf(stderr, "\t-V: print the version\n");
    exit(1);
}
Пример #16
0
/**
 * Display information about the disk image set.
 *
 * @param img_info Disk image to analyze
 * @param hFile Handle to print information to
 */
void
split_imgstat(TSK_IMG_INFO * img_info, FILE * hFile)
{
    IMG_SPLIT_INFO *split_info = (IMG_SPLIT_INFO *) img_info;
    int i;

    tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n");
    tsk_fprintf(hFile, "--------------------------------------------\n");
    tsk_fprintf(hFile, "Image Type: split\n");
    tsk_fprintf(hFile, "\nSize in bytes: %" PRIuOFF "\n", img_info->size);

    tsk_fprintf(hFile, "\n--------------------------------------------\n");
    tsk_fprintf(hFile, "Split Information:\n");

    for (i = 0; i < split_info->num_img; i++) {
        tsk_fprintf(hFile, "%s  (%" PRIuOFF " to %" PRIuOFF ")\n",
            split_info->images[i],
            (OFF_T) (i == 0) ? 0 : split_info->max_off[i - 1],
            (OFF_T) (split_info->max_off[i] - 1));
    }
}
Пример #17
0
static void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("usage: %s [-tvV] [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] image\n"),
        progname);
    tsk_fprintf(stderr, "\t-t: display type only\n");
    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-f fstype: File system type (use '-f list' for supported types)\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
    tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: Print version\n");

    exit(1);
}
Пример #18
0
/* SLACK SPACE  call backs */
static TSK_WALK_RET_ENUM
count_slack_file_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off,
    TSK_DADDR_T addr, char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags,
    void *ptr)
{
    BLKCALC_DATA *data = (BLKCALC_DATA *) ptr;

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "count_slack_file_act: Remaining File:  %" PRIuOFF
            "  Buffer: %" PRIuSIZE "\n", data->flen, size);

    /* This is not the last data unit */
    if (data->flen >= size) {
        data->flen -= size;
    }
    /* We have passed the end of the allocated space */
    else if (data->flen == 0) {
        if (data->count-- == 0) {
            tsk_printf("%" PRIuDADDR "\n", addr);
            data->found = 1;
            return TSK_WALK_STOP;

        }
    }
    /* This is the last data unit and there is unused space */
    else if (data->flen < size) {
        if (data->count-- == 0) {
            tsk_printf("%" PRIuDADDR "\n", addr);
            data->found = 1;
            return TSK_WALK_STOP;

        }
        data->flen = 0;
    }

    return TSK_WALK_CONT;
}
Пример #19
0
static int
tsk_printf_conv(WCHAR * wbuf, int wlen, char *msg, va_list * args)
{

    char *cbuf;
    UTF8 *ptr8;
    UTF16 *ptr16;
    int retVal;
    size_t len, clen;

    wbuf[0] = '\0';

    clen = wlen * 3;
    if (NULL == (cbuf = (char *) tsk_malloc(clen))) {
        return 1;
    }
    memset(cbuf, 0, clen);

    vsnprintf_s(cbuf, clen - 1, _TRUNCATE, msg, *args);
    len = strlen(cbuf);

    //Convert to UTF-16
    ptr8 = (UTF8 *) cbuf;
    ptr16 = (UTF16 *) wbuf;
    retVal =
        tsk_UTF8toUTF16(&ptr8, &ptr8[len + 1], &ptr16, &ptr16[wlen],
        TSKlenientConversion);
    if (retVal != TSKconversionOK) {
        *ptr16 = '\0';
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "tsk_printf_conv: error converting string to UTF-16\n");
    }
    free(cbuf);

    return 0;
}
Пример #20
0
/**
 * Open the Update Sequence Number Journal stored at the inode inum.
 *
 * @param ntfs File system where the journal is stored
 * @param inum file reference number where the USN journal is located
 * @returns 0 on success, 1 otherwise
 */
uint8_t
tsk_ntfs_usnjopen(TSK_FS_INFO *fs, TSK_INUM_T inum)
{
    NTFS_INFO *ntfs = (NTFS_INFO*)fs;

    tsk_error_reset();

    if (ntfs == NULL || ntfs->fs_info.ftype != TSK_FS_TYPE_NTFS) {
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr("Invalid FS type in tsk_ntfs_usnjopen");
        return 1;
    }

    /* Initialize usnjinfo support structure */
    ntfs->usnjinfo = tsk_malloc(sizeof *ntfs->usnjinfo);
    if (ntfs->usnjinfo == NULL)
        return 1;

    ntfs->usnjinfo->usnj_inum = inum;
    ntfs->usnjinfo->bsize = ntfs->fs_info.block_size;

    ntfs->usnjinfo->fs_file = tsk_fs_file_open_meta(&ntfs->fs_info, NULL, inum);
    if (ntfs->usnjinfo->fs_file == NULL) {
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr("ntfs_usnjopen: tsk_fs_file_open_meta");
        free(ntfs->usnjinfo);
        return 1;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr, "usn journal opened at inode %" PRIuINUM
                    " bsize: %" PRIu32 "\n",
                    ntfs->usnjinfo->usnj_inum, ntfs->usnjinfo->bsize);

    return 0;
}
Пример #21
0
void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("%s [-i imgtype] [-b dev_sector_size] [-o imgoffset] [-vV] [-t vstype] image [images]\n"),
        progname);
    tsk_fprintf(stderr,
        "\t-t vstype: The volume system type (use '-t list' for list of supported types)\n");
    tsk_fprintf(stderr,
        "\t-i imgtype: The format of the image file (use '-i list' for list of supported types)\n");
    tsk_fprintf(stderr,
        "\t-b dev_sector_size: The size (in bytes) of the device sectors\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: Offset to the start of the volume that contains the partition system (in sectors)\n");
    tsk_fprintf(stderr, "\t-v: verbose output\n");
    tsk_fprintf(stderr, "\t-V: print the version\n");
    exit(1);
}
Пример #22
0
static void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("usage: %s [-vV] [-i imgtype] [-b dev_sector_size] [-s start_sector] [-e stop_sector] 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-s start_sector: The sector number to start at\n");
    tsk_fprintf(stderr,
        "\t-e stop_sector:  The sector number to stop at\n");
    tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: Print version\n");

    exit(1);
}
static void
usage()
{
    TFPRINTF(stderr,
             _TSK_T
             ("usage: %s [-vV] [-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-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: Print version\n");
    tsk_fprintf(stderr,
                "\t-z: Time zone of original machine (i.e. EST5EDT or GMT) (only useful with -l)\n");
    tsk_fprintf(stderr,
                "\t-s seconds: Time skew of original machine (in seconds) (only useful with -l & -m)\n");


    exit(1);
}
Пример #24
0
/** \internal
 * Process a directory and load up FS_DIR with the entries. If a pointer to
 * an already allocated FS_DIR struture is given, it will be cleared.  If no existing
 * FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return
 * value is error or corruption, then the FS_DIR structure could
 * have entries (depending on when the error occured).
 *
 * @param a_fs File system to analyze
 * @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
 * structure or a new structure.
 * @param a_addr Address of directory to process.
 * @returns error, corruption, ok etc.
 */
TSK_RETVAL_ENUM
ffs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
                  TSK_INUM_T a_addr)
{
    TSK_OFF_T size;
    FFS_INFO *ffs = (FFS_INFO *) a_fs;
    char *dirbuf;
    int nchnk, cidx;
    TSK_FS_LOAD_FILE load_file;
    TSK_FS_DIR *fs_dir;

    /* If we get corruption in one of the blocks, then continue processing.
     * retval_final will change when corruption is detected.  Errors are
     * returned immediately. */
    TSK_RETVAL_ENUM retval_tmp;
    TSK_RETVAL_ENUM retval_final = TSK_OK;


    if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("ffs_dir_open_meta: Invalid inode value: %"
                             PRIuINUM, a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
        ("ffs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
                    "ffs_dir_open_meta: Processing directory %" PRIuINUM "\n",
                    a_addr);

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir =
                             tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    if ((fs_dir->fs_file =
                tsk_fs_file_open_meta(a_fs, NULL, a_addr)) == NULL) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ffs_dir_open_meta");
        return TSK_COR;
    }

    /* make a copy of the directory contents that we can process */
    /* round up cause we want the slack space too */
    size = roundup(fs_dir->fs_file->meta->size, FFS_DIRBLKSIZ);
    if ((dirbuf = tsk_malloc((size_t) size)) == NULL) {
        return TSK_ERR;
    }

    load_file.total = load_file.left = (size_t) size;
    load_file.base = load_file.cur = dirbuf;

    if (tsk_fs_file_walk(fs_dir->fs_file,
                         TSK_FS_FILE_WALK_FLAG_SLACK,
                         tsk_fs_load_file_action, (void *) &load_file)) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ffs_dir_open_meta");
        free(dirbuf);
        return TSK_COR;
    }

    /* Not all of the directory was copied, so we return */
    if (load_file.left > 0) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_FWALK);
        tsk_error_set_errstr("ffs_dir_open_meta: Error reading directory %"
                             PRIuINUM, a_addr);
        free(dirbuf);
        return TSK_COR;
    }

    /* Directory entries are written in chunks of DIRBLKSIZ
     ** determine how many chunks of this size we have to read to
     ** get a full block
     **
     ** Entries do not cross over the DIRBLKSIZ boundary
     */
    nchnk = (int) (size) / (FFS_DIRBLKSIZ) + 1;

    for (cidx = 0; cidx < nchnk && (int64_t) size > 0; cidx++) {
        int len = (FFS_DIRBLKSIZ < size) ? FFS_DIRBLKSIZ : (int) size;

        retval_tmp =
            ffs_dent_parse_block(ffs, fs_dir,
                                 (fs_dir->fs_file->
                                  meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
                                 dirbuf + cidx * FFS_DIRBLKSIZ, len);

        if (retval_tmp == TSK_ERR) {
            retval_final = TSK_ERR;
            break;
        }
        else if (retval_tmp == TSK_COR) {
            retval_final = TSK_COR;
        }
        size -= len;
    }
    free(dirbuf);

    // if we are listing the root directory, add the Orphan directory entry
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval_final;
}
Пример #25
0
TSK_VS_INFO *
tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset)
{
    TSK_VS_INFO *vs;

    // clean up any errors that are lying around
    tsk_error_reset();

    vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs));
    if (vs == NULL)
        return NULL;

    vs->img_info = img_info;
    vs->vstype = TSK_VS_TYPE_GPT;
    vs->tag = TSK_VS_INFO_TAG;

    /* If an offset was given, then use that too */
    vs->offset = offset;

    /* inititialize settings */
    vs->part_list = NULL;
    vs->part_count = 0;
    vs->endian = 0;
    vs->block_size = img_info->sector_size;

    /* Assign functions */
    vs->close = gpt_close;

    /* Load the partitions into the sorted list */
    if (gpt_load_table(vs)) {
        int found = 0;
        if (tsk_verbose)
            tsk_fprintf(stderr, "gpt_open: Trying other sector sizes\n");

        /* Before we give up, lets try some other sector sizes */
        vs->block_size = 512;
        while (vs->block_size <= 8192) {
            if (tsk_verbose)
                tsk_fprintf(stderr, "gpt_open: Trying sector size: %d\n",
                    vs->block_size);

            if (gpt_load_table(vs)) {
                vs->block_size *= 2;
                continue;
            }
            found = 1;
            break;
        }

        if (found == 0) {
            gpt_close(vs);
            return NULL;
        }
    }


    /* fill in the sorted list with the 'unknown' values */
    if (tsk_vs_part_unused(vs)) {
        gpt_close(vs);
        return NULL;
    }

    return vs;
}
Пример #26
0
/* 
 * Process the partition table at the sector address 
 * 
 * It is loaded into the internal sorted list 
 */
static uint8_t
gpt_load_table(TSK_VS_INFO * vs)
{
    gpt_head *head;
    gpt_entry *ent;
    dos_sect *dos_part;
    unsigned int i, a;
    uint32_t ent_size;
    char *safe_str, *head_str, *tab_str, *ent_buf;
    ssize_t cnt;
    char *sect_buf;
    TSK_DADDR_T taddr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    if (tsk_verbose)
        tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n",
            taddr);

    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
        return 1;
    dos_part = (dos_sect *) sect_buf;

    cnt = tsk_vs_read_block
        (vs, GPT_PART_SOFFSET, sect_buf, vs->block_size);
    /* if -1, then tsk_errno is already set */
    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2
            ("Error reading DOS safety partition table in Sector: %"
            PRIuDADDR, taddr);
        free(sect_buf);
        return 1;
    }

    /* Sanity Check */
    if (tsk_vs_guessu16(vs, dos_part->magic, DOS_MAGIC)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("Missing DOS safety partition (invalid magic) (Sector: %"
            PRIuDADDR ")", taddr);
        free(sect_buf);
        return 1;
    }

    if (dos_part->ptable[0].ptype != GPT_DOS_TYPE) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("Missing DOS safety partition (invalid type in table: %d)",
            dos_part->ptable[0].ptype);
        free(sect_buf);
        return 1;
    }

    /* Read the GPT header */
    head = (gpt_head *) sect_buf;
    cnt = tsk_vs_read_block
        (vs, GPT_PART_SOFFSET + 1, sect_buf, vs->block_size);
    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2("GPT Header structure in Sector: %"
            PRIuDADDR, taddr + 1);
        free(sect_buf);
        return 1;
    }

    if (tsk_getu64(vs->endian, &head->signature) != GPT_HEAD_SIG) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr("GPT Header: %" PRIx64, tsk_getu64(vs->endian,
                &head->signature));
        free(sect_buf);
        return 1;
    }

    // now that we checked the sig, lets make the meta  entries
    if ((safe_str = tsk_malloc(16)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(safe_str, 16, "Safety Table");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 0, (TSK_DADDR_T) 1,
            TSK_VS_PART_FLAG_META, safe_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }


    if ((head_str = tsk_malloc(16)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(head_str, 16, "GPT Header");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 1,
            (TSK_DADDR_T) ((tsk_getu32(vs->endian,
                        &head->head_size_b) + (vs->block_size-1)) / vs->block_size),
            TSK_VS_PART_FLAG_META, head_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }

    /* Allocate a buffer for each table entry */
    ent_size = tsk_getu32(vs->endian, &head->tab_size_b);
    if (ent_size < sizeof(gpt_entry)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr("Header reports partition entry size of %"
            PRIu32 " and not %" PRIuSIZE "", ent_size, sizeof(gpt_entry));
        free(sect_buf);
        return 1;
    }

    if ((tab_str = tsk_malloc(20)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(tab_str, 20, "Partition Table");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) tsk_getu64(vs->endian,
                &head->tab_start_lba),
            (TSK_DADDR_T) ((ent_size * tsk_getu32(vs->endian,
                        &head->tab_num_ent) + (vs->block_size-1)) / vs->block_size),
            TSK_VS_PART_FLAG_META, tab_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }


    /* Process the partition table */
    if ((ent_buf = tsk_malloc(vs->block_size)) == NULL) {
        free(sect_buf);
        return 1;
    }

    i = 0;
    for (a = 0; i < tsk_getu32(vs->endian, &head->tab_num_ent); a++) {
        char *name;

        /* Read a sector */
        cnt = tsk_vs_read_block(vs,
            tsk_getu64(vs->endian, &head->tab_start_lba) + a,
            ent_buf, vs->block_size);
        if (cnt != vs->block_size) {
            if (cnt >= 0) {
                tsk_error_reset();
                tsk_error_set_errno(TSK_ERR_VS_READ);
            }
            tsk_error_set_errstr2
                ("Error reading GPT partition table sector : %" PRIuDADDR,
                tsk_getu64(vs->endian, &head->tab_start_lba) + a);
            free(ent_buf);
            free(sect_buf);
            return 1;
        }

        /* Process the sector */
        ent = (gpt_entry *) ent_buf;
        for (; (uintptr_t) ent < (uintptr_t) ent_buf + vs->block_size &&
            i < tsk_getu32(vs->endian, &head->tab_num_ent); i++) {

            UTF16 *name16;
            UTF8 *name8;
            int retVal;

            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "gpt_load: %d  Starting Sector: %" PRIu64
                    "  End: %" PRIu64 " Flag: %" PRIx64 "\n", i,
                    tsk_getu64(vs->endian, ent->start_lba),
                    tsk_getu64(vs->endian, ent->end_lba),
                    tsk_getu64(vs->endian, ent->flags));


            if (tsk_getu64(vs->endian, ent->start_lba) == 0) {
                ent++;
                continue;
            }

            // make sure the first couple are in the image bounds
            if ((i < 2)
                && (tsk_getu64(vs->endian, ent->start_lba) > max_addr)) {
                tsk_error_reset();
                tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
                tsk_error_set_errstr
                    ("gpt_load_table: Starting sector too large for image");
                free(sect_buf);
                free(ent_buf);
                return 1;
            }


            if ((name = tsk_malloc(256)) == NULL) {
                free(sect_buf);
                free(ent_buf);
                return 1;
            }

            name16 = (UTF16 *) ((uintptr_t) ent->name);
            name8 = (UTF8 *) name;

            retVal =
                tsk_UTF16toUTF8(vs->endian, (const UTF16 **) &name16,
                (UTF16 *) ((uintptr_t) name16 + sizeof(ent->name)),
                &name8,
                (UTF8 *) ((uintptr_t) name8 + 256), TSKlenientConversion);

            if (retVal != TSKconversionOK) {
                if (tsk_verbose)
                    tsk_fprintf(stderr,
                        "gpt_load_table: Error converting name to UTF8: %d\n",
                        retVal);
                *name = '\0';
            }

            if (NULL == tsk_vs_part_add(vs,
                    (TSK_DADDR_T) tsk_getu64(vs->endian, ent->start_lba),
                    (TSK_DADDR_T) (tsk_getu64(vs->endian,
                            ent->end_lba) - tsk_getu64(vs->endian,
                            ent->start_lba) + 1), TSK_VS_PART_FLAG_ALLOC,
                    name, -1, i)) {
                free(sect_buf);
                free(ent_buf);
                return 1;
            }

            ent++;
        }
    }

    free(sect_buf);
    free(ent_buf);
    return 0;
}
Пример #27
0
/* dir_walk local function that is used for recursive calls.  Callers
 * should initially call the non-local version. */
static TSK_WALK_RET_ENUM
tsk_fs_dir_walk_lcl(TSK_FS_INFO * a_fs, DENT_DINFO * a_dinfo,
    TSK_INUM_T a_addr, TSK_FS_DIR_WALK_FLAG_ENUM a_flags,
    TSK_FS_DIR_WALK_CB a_action, void *a_ptr)
{
    TSK_FS_DIR *fs_dir;
    TSK_FS_FILE *fs_file;
    size_t i;

    // get the list of entries in the directory
    if ((fs_dir = tsk_fs_dir_open_meta(a_fs, a_addr)) == NULL) {
        return TSK_WALK_ERROR;
    }

    /* Allocate a file structure for the callbacks.  We
     * will allocate fs_meta structures as needed and
     * point into the fs_dir structure for the names. */
    if ((fs_file = tsk_fs_file_alloc(a_fs)) == NULL) {
        tsk_fs_dir_close(fs_dir);
        return TSK_WALK_ERROR;
    }

    for (i = 0; i < fs_dir->names_used; i++) {
        TSK_WALK_RET_ENUM retval;

        /* Point name to the buffer of names.  We need to be
         * careful about resetting this before we free fs_file */
        fs_file->name = (TSK_FS_NAME *) & fs_dir->names[i];

        /* load the fs_meta structure if possible.
         * Must have non-zero inode addr or have allocated name (if inode is 0) */
        if (((fs_file->name->meta_addr)
                || (fs_file->name->flags & TSK_FS_NAME_FLAG_ALLOC))) {
            if (a_fs->file_add_meta(a_fs, fs_file,
                    fs_file->name->meta_addr)) {
                if (tsk_verbose)
                    tsk_error_print(stderr);
                tsk_error_reset();
            }
        }

        // call the action if we have the right flags.
        if ((fs_file->name->flags & a_flags) == fs_file->name->flags) {
            retval = a_action(fs_file, a_dinfo->dirs, a_ptr);
            if (retval == TSK_WALK_STOP) {
                tsk_fs_dir_close(fs_dir);
                fs_file->name = NULL;
                tsk_fs_file_close(fs_file);

                /* free the list -- fs_dir_walk has no way
                 * of knowing that we stopped early w/out error.
                 */
                if (a_dinfo->save_inum_named) {
                    tsk_list_free(a_dinfo->list_inum_named);
                    a_dinfo->list_inum_named = NULL;
                    a_dinfo->save_inum_named = 0;
                }
                return TSK_WALK_STOP;
            }
            else if (retval == TSK_WALK_ERROR) {
                tsk_fs_dir_close(fs_dir);
                fs_file->name = NULL;
                tsk_fs_file_close(fs_file);
                return TSK_WALK_ERROR;
            }
        }

        // save the inode info for orphan finding - if requested
        if ((a_dinfo->save_inum_named) && (fs_file->meta)
            && (fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC)) {

            if (tsk_list_add(&a_dinfo->list_inum_named,
                    fs_file->meta->addr)) {

                // if there is an error, then clear the list
                tsk_list_free(a_dinfo->list_inum_named);
                a_dinfo->list_inum_named = NULL;
                a_dinfo->save_inum_named = 0;
            }
        }

        /* Recurse into a directory if:
         * - Both dir entry and inode have DIR type (or name is undefined)
         * - Recurse flag is set
         * - dir entry is allocated OR both are unallocated
         * - not one of the '.' or '..' entries
         * - A Non-Orphan Dir or the Orphan Dir with the NOORPHAN flag not set.
         */
        if (((fs_file->name->type == TSK_FS_NAME_TYPE_DIR)
                || (fs_file->name->type == TSK_FS_NAME_TYPE_UNDEF))
            && (fs_file->meta)
            && (fs_file->meta->type == TSK_FS_META_TYPE_DIR)
            && (a_flags & TSK_FS_DIR_WALK_FLAG_RECURSE)
            && ((fs_file->name->flags & TSK_FS_NAME_FLAG_ALLOC)
                || ((fs_file->name->flags & TSK_FS_NAME_FLAG_UNALLOC)
                    && (fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC))
            )
            && (!TSK_FS_ISDOT(fs_file->name->name))
            && ((fs_file->name->meta_addr != TSK_FS_ORPHANDIR_INUM(a_fs))
                || ((a_flags & TSK_FS_DIR_WALK_FLAG_NOORPHAN) == 0))
            ) {

            /* Make sure we do not get into an infinite loop */
            if (0 == tsk_stack_find(a_dinfo->stack_seen,
                    fs_file->name->meta_addr)) {
                int depth_added = 0;
                uint8_t save_bak = 0;

                if (tsk_stack_push(a_dinfo->stack_seen,
                        fs_file->name->meta_addr)) {
                    tsk_fs_dir_close(fs_dir);
                    fs_file->name = NULL;
                    tsk_fs_file_close(fs_file);
                    return TSK_WALK_ERROR;
                }

                if ((a_dinfo->depth < MAX_DEPTH) &&
                    (DIR_STRSZ >
                        strlen(a_dinfo->dirs) +
                        strlen(fs_file->name->name))) {
                    a_dinfo->didx[a_dinfo->depth] =
                        &a_dinfo->dirs[strlen(a_dinfo->dirs)];
                    strncpy(a_dinfo->didx[a_dinfo->depth],
                        fs_file->name->name,
                        DIR_STRSZ - strlen(a_dinfo->dirs));
                    strncat(a_dinfo->dirs, "/", DIR_STRSZ);
                    depth_added = 1;
                }
                a_dinfo->depth++;

                /* We do not want to save info about named unalloc files
                 * when we go into the Orphan directory (because then we have
                 * no orphans).  So, disable it for this recursion.
                 */
                if (fs_file->name->meta_addr ==
                    TSK_FS_ORPHANDIR_INUM(a_fs)) {
                    save_bak = a_dinfo->save_inum_named;
                    a_dinfo->save_inum_named = 0;
                }
                retval = tsk_fs_dir_walk_lcl(a_fs,
                    a_dinfo, fs_file->name->meta_addr, a_flags,
                    a_action, a_ptr);
                if (retval == TSK_WALK_ERROR) {
                    /* If this fails because the directory could not be
                     * loaded, then we still continue */
                    if (tsk_verbose) {
                        tsk_fprintf(stderr,
                            "tsk_fs_dir_walk_lcl: error reading directory: %"
                            PRIuINUM "\n", fs_file->name->meta_addr);
                        tsk_error_print(stderr);
                    }

                    tsk_error_reset();
                }
                else if (retval == TSK_WALK_STOP) {
                    tsk_fs_dir_close(fs_dir);
                    fs_file->name = NULL;
                    tsk_fs_file_close(fs_file);
                    return TSK_WALK_STOP;
                }

                // reset the save status
                if (fs_file->name->meta_addr ==
                    TSK_FS_ORPHANDIR_INUM(a_fs)) {
                    a_dinfo->save_inum_named = save_bak;
                }

                tsk_stack_pop(a_dinfo->stack_seen);
                a_dinfo->depth--;
                if (depth_added)
                    *a_dinfo->didx[a_dinfo->depth] = '\0';
            }
            else {
                if (tsk_verbose)
                    fprintf(stderr,
                        "tsk_fs_dir_walk_lcl: Loop detected with address %"
                        PRIuINUM, fs_file->name->meta_addr);
            }
        }

        // remove the pointer to name buffer
        fs_file->name = NULL;

        // free the metadata if we allocated it
        if (fs_file->meta) {
            tsk_fs_meta_close(fs_file->meta);
            fs_file->meta = NULL;
        }
    }

    tsk_fs_dir_close(fs_dir);
    fs_file->name = NULL;
    tsk_fs_file_close(fs_file);
    return TSK_WALK_CONT;
}
Пример #28
0
/** \internal
 * Add a FS_DENT structure to a FS_DIR structure by copying its
 * contents into the internal buffer. Checks for
 * duplicates and expands buffer as needed.
 * @param a_fs_dir DIR to add to
 * @param a_fs_name DENT to add
 * @returns 1 on error (memory allocation problems) and 0 on success
 */
uint8_t
tsk_fs_dir_add(TSK_FS_DIR * a_fs_dir, const TSK_FS_NAME * a_fs_name)
{
    TSK_FS_NAME *fs_name_dest = NULL;
    size_t i;

    /* see if we already have it in the buffer / queue
     * We skip this check for FAT because it will always fail because two entries
     * never have the same meta address. */
    // @@@ We could do something more effecient here too with orphan files because we do not 
    // need to check the contents of that directory either and this takes a lot of time on those
    // large images.
	if (TSK_FS_TYPE_ISFAT(a_fs_dir->fs_info->ftype) == 0) {
		for (i = 0; i < a_fs_dir->names_used; i++) {
			if ((a_fs_name->meta_addr == a_fs_dir->names[i].meta_addr) &&
				(strcmp(a_fs_name->name, a_fs_dir->names[i].name) == 0)) {

				if (tsk_verbose)
					tsk_fprintf(stderr,
						"tsk_fs_dir_add: removing duplicate entry: %s (%"
						PRIuINUM ")\n", a_fs_name->name, a_fs_name->meta_addr);

				/* We do not check type because then we cannot detect NTFS orphan file
				 * duplicates that are added as "-/r" while a similar entry exists as "r/r"
				 (a_fs_name->type == a_fs_dir->names[i].type)) { */

				// if the one in the list is unalloc and we have an alloc, replace it
				if ((a_fs_dir->names[i].flags & TSK_FS_NAME_FLAG_UNALLOC) &&
					(a_fs_name->flags & TSK_FS_NAME_FLAG_ALLOC)) {
					fs_name_dest = &a_fs_dir->names[i];

					// free the memory - not the most effecient, but prevents
					// duplicate code.
					if (fs_name_dest->name) {
						free(fs_name_dest->name);
						fs_name_dest->name = NULL;
						fs_name_dest->name_size = 0;
					}
					if (fs_name_dest->shrt_name) {
						free(fs_name_dest->shrt_name);
						fs_name_dest->shrt_name = NULL;
						fs_name_dest->shrt_name_size = 0;
					}
					break;
				}
				else {
					return 0;
				}
			}
		}
	}

    if (fs_name_dest == NULL) {
        // make sure we got the room
        if (a_fs_dir->names_used >= a_fs_dir->names_alloc) {
            if (tsk_fs_dir_realloc(a_fs_dir, a_fs_dir->names_used + 512))
                return 1;
        }

        fs_name_dest = &a_fs_dir->names[a_fs_dir->names_used++];
    }

    if (tsk_fs_name_copy(fs_name_dest, a_fs_name))
        return 1;

    // add the parent address
    if (a_fs_dir->addr)
        fs_name_dest->par_addr = a_fs_dir->addr;

    return 0;
}
Пример #29
0
/* main - open file system, list inode info */
int
main(int argc, char **argv1)
{
    TSK_IMG_TYPE_ENUM imgtype = TSK_IMG_TYPE_DETECT;
    TSK_IMG_INFO *img;

    TSK_OFF_T imgaddr = 0;
    TSK_FS_TYPE_ENUM fstype = TSK_FS_TYPE_DETECT;
    TSK_FS_INFO *fs;

    TSK_TCHAR *cp, *dash;
    TSK_INUM_T istart = 0, ilast = 0;
    int ch;
    int flags = TSK_FS_META_FLAG_UNALLOC | TSK_FS_META_FLAG_USED;
    int ils_flags = 0;
    int set_range = 1;
    TSK_TCHAR *image = NULL;
    int32_t sec_skew = 0;
    TSK_TCHAR **argv;
    unsigned int ssize = 0;

#ifdef TSK_WIN32
    // On Windows, get the wide arguments (mingw doesn't support wmain)
    argv = CommandLineToArgvW(GetCommandLineW(), &argc);
    if (argv == NULL) {
        fprintf(stderr, "Error getting wide arguments\n");
        exit(1);
    }
#else
    argv = (TSK_TCHAR **) argv1;
#endif

    progname = argv[0];
    setlocale(LC_ALL, "");

    /*
     * Provide convenience options for the most commonly selected feature
     * combinations.
     */
    while ((ch =
            GETOPT(argc, argv, _TSK_T("aAb:ef:i:lLmo:Oprs:vVzZ"))) > 0) {
        switch (ch) {
        case _TSK_T('?'):
        default:
            TFPRINTF(stderr, _TSK_T("Invalid argument: %s\n"),
                argv[OPTIND]);
            usage();
        case _TSK_T('b'):
            ssize = (unsigned int) TSTRTOUL(OPTARG, &cp, 0);
            if (*cp || *cp == *OPTARG || ssize < 1) {
                TFPRINTF(stderr,
                    _TSK_T
                    ("invalid argument: sector size must be positive: %s\n"),
                    OPTARG);
                usage();
            }
            break;
        case _TSK_T('f'):
            if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) {
                tsk_fs_type_print(stderr);
                exit(1);
            }
            fstype = tsk_fs_type_toid(OPTARG);
            if (fstype == TSK_FS_TYPE_UNSUPP) {
                TFPRINTF(stderr,
                    _TSK_T("Unsupported file system type: %s\n"), OPTARG);
                usage();
            }
            break;
        case _TSK_T('i'):
            if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) {
                tsk_img_type_print(stderr);
                exit(1);
            }
            imgtype = tsk_img_type_toid(OPTARG);
            if (imgtype == TSK_IMG_TYPE_UNSUPP) {
                TFPRINTF(stderr, _TSK_T("Unsupported image type: %s\n"),
                    OPTARG);
                usage();
            }
            break;
        case _TSK_T('e'):
            flags |= (TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC);
            flags &= ~TSK_FS_META_FLAG_USED;
            break;
        case _TSK_T('m'):
            ils_flags |= TSK_FS_ILS_MAC;
            break;
        case _TSK_T('o'):
            if ((imgaddr = tsk_parse_offset(OPTARG)) == -1) {
                tsk_error_print(stderr);
                exit(1);
            }
            break;
        case _TSK_T('O'):
            flags |= TSK_FS_META_FLAG_UNALLOC;
            flags &= ~TSK_FS_META_FLAG_ALLOC;
            ils_flags |= TSK_FS_ILS_OPEN;
            break;
        case _TSK_T('p'):
            flags |= (TSK_FS_META_FLAG_ORPHAN | TSK_FS_META_FLAG_UNALLOC);
            flags &= ~TSK_FS_META_FLAG_ALLOC;
            break;
        case _TSK_T('r'):
            flags |= (TSK_FS_META_FLAG_UNALLOC | TSK_FS_META_FLAG_USED);
            flags &= ~TSK_FS_META_FLAG_ALLOC;
            break;
        case _TSK_T('s'):
            sec_skew = TATOI(OPTARG);
            break;
        case _TSK_T('v'):
            tsk_verbose++;
            break;
        case _TSK_T('V'):
            tsk_version_print(stdout);
            exit(0);

            /*
             * Provide fine controls to tweak one feature at a time.
             */
        case _TSK_T('a'):
            flags |= TSK_FS_META_FLAG_ALLOC;
			flags &= ~TSK_FS_META_FLAG_UNALLOC;
            break;
        case _TSK_T('A'):
            flags |= TSK_FS_META_FLAG_UNALLOC;
            break;
        case _TSK_T('l'):
            ils_flags |= TSK_FS_ILS_LINK;
            break;
        case _TSK_T('L'):
            ils_flags |= TSK_FS_ILS_UNLINK;
            break;
        case _TSK_T('z'):
            flags |= TSK_FS_META_FLAG_UNUSED;
            break;
        case _TSK_T('Z'):
            flags |= TSK_FS_META_FLAG_USED;
            break;
        }
    }

    if (OPTIND >= argc) {
        tsk_fprintf(stderr, "Missing image name\n");
        usage();
    }

    if ((ils_flags & TSK_FS_ILS_LINK) && (ils_flags & TSK_FS_ILS_UNLINK)) {
        tsk_fprintf(stderr,
            "ERROR: Only linked or unlinked should be used\n");
        usage();
    }

    /* We need to determine if an inode or inode range was given */
    if ((dash = TSTRCHR(argv[argc - 1], _TSK_T('-'))) == NULL) {
        /* Check if is a single number */
        istart = TSTRTOULL(argv[argc - 1], &cp, 0);
        if (*cp || *cp == *argv[argc - 1]) {
            /* Not a number - consider it a file name */
            image = argv[OPTIND];
            if ((img =
                    tsk_img_open(argc - OPTIND, &argv[OPTIND],
                        imgtype, ssize)) == NULL) {
                tsk_error_print(stderr);
                exit(1);
            }
            if ((imgaddr * img->sector_size) >= img->size) {
                tsk_fprintf(stderr,
                    "Sector offset supplied is larger than disk image (maximum: %"
                    PRIu64 ")\n", img->size / img->sector_size);
                exit(1);
            }
        }
        else {
            /* Single address set end addr to start */
            ilast = istart;
            set_range = 0;
            image = argv[OPTIND];
            if ((img =
                    tsk_img_open(argc - OPTIND - 1, &argv[OPTIND],
                        imgtype, ssize)) == NULL) {
                tsk_error_print(stderr);
                exit(1);
            }
            if ((imgaddr * img->sector_size) >= img->size) {
                tsk_fprintf(stderr,
                    "Sector offset supplied is larger than disk image (maximum: %"
                    PRIu64 ")\n", img->size / img->sector_size);
                exit(1);
            }
        }
    }
    else {
        /* We have a dash, but it could be part of the file name */
        *dash = '\0';

        istart = TSTRTOULL(argv[argc - 1], &cp, 0);
        if (*cp || *cp == *argv[argc - 1]) {
            /* Not a number - consider it a file name */
            *dash = _TSK_T('-');
            image = argv[OPTIND];
            if ((img =
                    tsk_img_open(argc - OPTIND, &argv[OPTIND],
                        imgtype, ssize)) == NULL) {
                tsk_error_print(stderr);
                exit(1);
            }
            if ((imgaddr * img->sector_size) >= img->size) {
                tsk_fprintf(stderr,
                    "Sector offset supplied is larger than disk image (maximum: %"
                    PRIu64 ")\n", img->size / img->sector_size);
                exit(1);
            }
        }
        else {
            dash++;
            ilast = TSTRTOULL(dash, &cp, 0);
            if (*cp || *cp == *dash) {
                /* Not a number - consider it a file name */
                dash--;
                *dash = '-';
                image = argv[OPTIND];
                if ((img =
                        tsk_img_open(argc - OPTIND, &argv[OPTIND],
                            imgtype, ssize)) == NULL) {
                    tsk_error_print(stderr);
                    exit(1);
                }
                if ((imgaddr * img->sector_size) >= img->size) {
                    tsk_fprintf(stderr,
                        "Sector offset supplied is larger than disk image (maximum: %"
                        PRIu64 ")\n", img->size / img->sector_size);
                    exit(1);
                }
            }
            else {
                set_range = 0;
                /* It was a block range, so do not include it in the open */
                image = argv[OPTIND];
                if ((img =
                        tsk_img_open(argc - OPTIND - 1, &argv[OPTIND],
                            imgtype, ssize)) == NULL) {
                    tsk_error_print(stderr);
                    exit(1);
                }
                if ((imgaddr * img->sector_size) >= img->size) {
                    tsk_fprintf(stderr,
                        "Sector offset supplied is larger than disk image (maximum: %"
                        PRIu64 ")\n", img->size / img->sector_size);
                    exit(1);
                }
            }
        }
    }

    if ((fs = tsk_fs_open_img(img, imgaddr * img->sector_size, fstype)) == NULL) {
        tsk_error_print(stderr);
        if (tsk_error_get_errno() == TSK_ERR_FS_UNSUPTYPE)
            tsk_fs_type_print(stderr);
        img->close(img);
        exit(1);
    }

    /* do we need to set the range or just check them? */
    if (set_range) {
        istart = fs->first_inum;
        ilast = fs->last_inum;
    }
    else {
        if (istart < fs->first_inum)
            istart = fs->first_inum;

        if (ilast > fs->last_inum)
            ilast = fs->last_inum;
    }

    /* NTFS uses alloc and link different than UNIX so change
     * the default behavior
     *
     * The link value can be > 0 on deleted files (even when closed)
     */

    /* NTFS and FAT have no notion of deleted but still open */
    if ((ils_flags & TSK_FS_ILS_OPEN) && (TSK_FS_TYPE_ISNTFS(fs->ftype)
            || TSK_FS_TYPE_ISFAT(fs->ftype))) {
        fprintf(stderr,
            "Error: '-O' argument does not work with NTFS and FAT images\n");
        exit(1);
    }

    if (tsk_fs_ils(fs, (TSK_FS_ILS_FLAG_ENUM) ils_flags, istart, ilast,
            (TSK_FS_META_FLAG_ENUM) flags, sec_skew, image)) {
        tsk_error_print(stderr);
        fs->close(fs);
        img->close(img);
        exit(1);
    }

    fs->close(fs);
    img->close(img);
    exit(0);
}
Пример #30
0
/* usage - explain and terminate */
static void
usage()
{
    TFPRINTF(stderr,
        _TSK_T
        ("usage: %s [-emOpvV] [-aAlLzZ] [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] [-s seconds] image [images] [inum[-end]]\n"),
        progname);
    tsk_fprintf(stderr, "\t-e: Display all inodes\n");
    tsk_fprintf(stderr, "\t-m: Display output in the mactime format\n");
    tsk_fprintf(stderr,
        "\t-O: Display inodes that are unallocated, but were sill open (UFS/ExtX only)\n");
    tsk_fprintf(stderr,
        "\t-p: Display orphan inodes (unallocated with no file name)\n");
    tsk_fprintf(stderr,
        "\t-s seconds: Time skew of original machine (in seconds)\n");
    tsk_fprintf(stderr, "\t-a: Allocated inodes\n");
    tsk_fprintf(stderr, "\t-A: Unallocated inodes\n");
    tsk_fprintf(stderr, "\t-l: Linked inodes\n");
    tsk_fprintf(stderr, "\t-L: Unlinked inodes\n");
    tsk_fprintf(stderr, "\t-z: Unused inodes\n");
    tsk_fprintf(stderr, "\t-Z: Used inodes\n");
    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-f fstype: File system type (use '-f list' for supported types)\n");
    tsk_fprintf(stderr,
        "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
    tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
    tsk_fprintf(stderr, "\t-V: Display version number\n");
    exit(1);
}