static TSK_WALK_RET_ENUM blkstat_act(const TSK_FS_BLOCK * fs_block, void *ptr) { tsk_printf("%s: %" PRIuDADDR "\n", fs_block->fs_info->duname, fs_block->addr); tsk_printf("%sAllocated%s\n", (fs_block->flags & TSK_FS_BLOCK_FLAG_ALLOC) ? "" : "Not ", (fs_block->flags & TSK_FS_BLOCK_FLAG_META) ? " (Meta)" : ""); if (TSK_FS_TYPE_ISFFS(fs_block->fs_info->ftype)) { FFS_INFO *ffs = (FFS_INFO *) fs_block->fs_info; tsk_printf("Group: %" PRI_FFSGRP "\n", ffs->grp_num); } else if (TSK_FS_TYPE_ISEXT(fs_block->fs_info->ftype)) { EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) fs_block->fs_info; if (fs_block->addr >= ext2fs->first_data_block) tsk_printf("Group: %" PRI_EXT2GRP "\n", ext2fs->grp_num); } else if (TSK_FS_TYPE_ISFAT(fs_block->fs_info->ftype)) { FATFS_INFO *fatfs = (FATFS_INFO *) fs_block->fs_info; /* Does this have a cluster address? */ if (fs_block->addr >= fatfs->firstclustsect) { tsk_printf("Cluster: %" PRIuDADDR "\n", (2 + (fs_block->addr - fatfs->firstclustsect) / fatfs->csize)); } } return TSK_WALK_STOP; }
/* * Find the inode that has allocated block blk * Return 1 on error, 0 if no error */ uint8_t tsk_fs_ifind_data(TSK_FS_INFO * fs, TSK_FS_IFIND_FLAG_ENUM lclflags, TSK_DADDR_T blk) { IFIND_DATA_DATA data; memset(&data, 0, sizeof(IFIND_DATA_DATA)); data.flags = lclflags; data.block = blk; if (fs->inode_walk(fs, fs->first_inum, fs->last_inum, TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC, ifind_data_act, &data)) { return 1; } /* If we did not find an inode yet, get the block's * flags so we can identify it as a meta data block */ if (!data.found) { TSK_FS_BLOCK *fs_block; if ((fs_block = tsk_fs_block_get(fs, NULL, blk)) != NULL) { if (fs_block->flags & TSK_FS_BLOCK_FLAG_META) { tsk_printf("Meta Data\n"); data.found = 1; } tsk_fs_block_free(fs_block); } } if (!data.found) { tsk_printf("Inode not found\n"); } return 0; }
/* call backs for listing details * * return 1 on error * */ static uint8_t print_list_head(TSK_FS_INFO * fs) { char hostnamebuf[BUFSIZ]; #ifndef TSK_WIN32 if (gethostname(hostnamebuf, sizeof(hostnamebuf) - 1) < 0) { if (tsk_verbose) tsk_fprintf(stderr, "dls_lib: error getting hostname: %s\n", strerror(errno)); strcpy(hostnamebuf, "unknown"); } hostnamebuf[sizeof(hostnamebuf) - 1] = 0; #else strcpy(hostnamebuf, "unknown"); #endif /* * Identify table type and table origin. */ tsk_printf("class|host|image|first_time|unit\n"); tsk_printf("dls|%s||%"PRIu64"|%s\n", hostnamebuf, (uint64_t)time(NULL), fs->duname); tsk_printf("addr|alloc\n"); return 0; }
/* this is a wrapper type function that takes care of the runtime * flags * * fs_attr should be set to NULL for all non-NTFS file systems */ static void printit(TSK_FS_FILE * fs_file, const char *a_path, const TSK_FS_ATTR * fs_attr, const FLS_DATA * fls_data) { TSK_FS_HASH_RESULTS hash_results; unsigned char null_buf[16]; unsigned int i; if ((!(fls_data->flags & TSK_FS_FLS_FULL)) && (a_path)) { uint8_t printed = 0; // lazy way to find out how many dirs there could be for (i = 0; a_path[i] != '\0'; i++) { if ((a_path[i] == '/') && (i != 0)) { tsk_fprintf(stdout, "+"); printed = 1; } } if (printed) tsk_fprintf(stdout, " "); } if (fls_data->flags & TSK_FS_FLS_MAC) { if (fls_data->flags & TSK_FS_FLS_HASH) { if(0 == tsk_fs_file_hash_calc(fs_file, &hash_results, TSK_BASE_HASH_MD5)){ tsk_fs_name_print_mac_md5(stdout, fs_file, a_path, fs_attr, fls_data->macpre, fls_data->sec_skew, hash_results.md5_digest); tsk_printf("\n"); } else{ // If the hash calculation had errors, pass in a buffer of nulls memset(null_buf, 0, 16); tsk_fs_name_print_mac_md5(stdout, fs_file, a_path, fs_attr, fls_data->macpre, fls_data->sec_skew, null_buf); tsk_printf("\n"); } } else { tsk_fs_name_print_mac(stdout, fs_file, a_path, fs_attr, fls_data->macpre, fls_data->sec_skew); tsk_printf("\n"); } } else if (fls_data->flags & TSK_FS_FLS_LONG) { tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info, fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0, fls_data->sec_skew); tsk_printf("\n"); } else { tsk_fs_name_print(stdout, fs_file, a_path, fs_file->fs_info, fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0); tsk_printf("\n"); } }
static void print_header(const TSK_VS_INFO * vs) { tsk_printf("%s\n", tsk_vs_type_todesc(vs->vstype)); tsk_printf("Offset Sector: %" PRIuDADDR "\n", (TSK_DADDR_T) (vs->offset / vs->block_size)); tsk_printf("Units are in %d-byte sectors\n\n", vs->block_size); if (print_bytes) tsk_printf (" Slot Start End Length Size Description\n"); else tsk_printf (" Slot Start End Length Description\n"); }
static void print_header(TSK_MM_INFO * mm) { tsk_printf("%s\n", mm->str_type); tsk_printf("Offset Sector: %" PRIuDADDR "\n", (DADDR_T) (mm->offset / mm->block_size)); tsk_printf("Units are in %d-byte sectors\n\n", mm->block_size); if (print_bytes) tsk_printf (" Slot Start End Length Size Description\n"); else tsk_printf (" Slot Start End Length Description\n"); }
static TSK_WALK_RET_ENUM print_list(const TSK_FS_BLOCK * fs_block, void *ptr) { tsk_printf("%" PRIuDADDR "|%s\n", fs_block->addr, (fs_block->flags & TSK_FS_BLOCK_FLAG_ALLOC) ? "a" : "f"); return TSK_WALK_CONT; }
/* this is a wrapper type function that takes care of the runtime * flags * * fs_attr should be set to NULL for all non-NTFS file systems */ static void printit(TSK_FS_FILE * fs_file, const char *a_path, const TSK_FS_ATTR * fs_attr, const FLS_DATA * fls_data) { unsigned int i; if ((!(fls_data->flags & TSK_FS_FLS_FULL)) && (a_path)) { uint8_t printed = 0; // lazy way to find out how many dirs there could be for (i = 0; a_path[i] != '\0'; i++) { if ((a_path[i] == '/') && (i != 0)) { tsk_fprintf(stdout, "+"); printed = 1; } } if (printed) tsk_fprintf(stdout, " "); } if (fls_data->flags & TSK_FS_FLS_MAC) { tsk_fs_name_print_mac(stdout, fs_file, a_path, fs_attr, fls_data->macpre, fls_data->sec_skew); } else if (fls_data->flags & TSK_FS_FLS_LONG) { tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info, fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0, fls_data->sec_skew); } else { tsk_fs_name_print(stdout, fs_file, a_path, fs_file->fs_info, fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0); tsk_printf("\n"); } }
/* * Find the inode that has allocated block blk * Return 1 on error, 0 if no error */ uint8_t tsk_fs_ifind_data(TSK_FS_INFO * fs, uint8_t lclflags, DADDR_T blk) { found = 0; localflags = lclflags; block = blk; if (fs->inode_walk(fs, fs->first_inum, fs->last_inum, TSK_FS_INODE_FLAG_ALLOC | TSK_FS_INODE_FLAG_UNALLOC, ifind_data_act, NULL)) { return 1; } /* * If we did not find an inode yet, we call block_walk for the * block to find out the associated flags so we can identify it as * a meta data block */ if (0 == found) { if (fs->block_walk(fs, block, block, (TSK_FS_BLOCK_FLAG_ENUM) (TSK_FS_BLOCK_FLAG_UNALLOC | TSK_FS_BLOCK_FLAG_ALLOC | TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_CONT), ifind_data_block_act, NULL)) { return 1; } } if (0 == found) { tsk_printf("Inode not found\n"); } return 0; }
/* dent call back for finding unallocated files based on parent directory */ static uint8_t ifind_par_act(TSK_FS_INFO * fs, TSK_FS_INODE * fs_inode, void *ptr) { TSK_FS_INODE_NAME_LIST *fs_name; /* go through each file name structure */ fs_name = fs_inode->name; while (fs_name) { if (fs_name->par_inode == parinode) { /* Fill in the basics of the fs_dent entry */ fs_dent->fsi = fs_inode; fs_dent->inode = fs_inode->addr; fs_dent->flags = TSK_FS_DENT_FLAG_UNALLOC; strncpy(fs_dent->name, fs_name->name, fs_dent->name_max); if (localflags & TSK_FS_IFIND_PAR_LONG) { tsk_fs_dent_print_long(stdout, fs_dent, fs, NULL); } else { tsk_fs_dent_print(stdout, fs_dent, fs, NULL); tsk_printf("\n"); } fs_dent->fsi = NULL; found = 1; } fs_name = fs_name->next; } return TSK_WALK_CONT; }
static TSK_WALK_RET_ENUM print_list(TSK_FS_INFO * fs, TSK_DADDR_T addr, char *buf, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr) { tsk_printf("%" PRIuDADDR "|%s\n", addr, (flags & TSK_FS_BLOCK_FLAG_ALLOC) ? "a" : "f"); return TSK_WALK_CONT; }
/* * if the block is a meta data block, then report that, otherwise * this is where we say that the inode was not found */ static uint8_t ifind_data_block_act(TSK_FS_INFO * fs, DADDR_T addr, char *buf, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr) { if (flags & TSK_FS_BLOCK_FLAG_META) { tsk_printf("Meta Data\n"); found = 1; } return TSK_WALK_STOP; }
/* ** count how many unalloc blocks there are. ** ** This is called for unalloc blocks only */ static TSK_WALK_RET_ENUM count_blkls_act(const TSK_FS_BLOCK * fs_block, void *ptr) { BLKCALC_DATA *data = (BLKCALC_DATA *) ptr; if (data->count-- == 0) { tsk_printf("%" PRIuDADDR "\n", fs_block->addr); data->found = 1; return TSK_WALK_STOP; } return TSK_WALK_CONT; }
/* 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; }
/* * file_walk action for non-ntfs */ static TSK_WALK_RET_ENUM ifind_data_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) { TSK_FS_INFO *fs = fs_file->fs_info; IFIND_DATA_DATA *data = (IFIND_DATA_DATA *) ptr; /* Ignore sparse blocks because they do not reside on disk */ if (flags & TSK_FS_BLOCK_FLAG_SPARSE) return TSK_WALK_CONT; if (addr == data->block) { if (TSK_FS_TYPE_ISNTFS(fs->ftype)) tsk_printf("%" PRIuINUM "-%" PRIu32 "-%" PRIu16 "\n", data->curinode, data->curtype, data->curid); else tsk_printf("%" PRIuINUM "\n", data->curinode); data->found = 1; return TSK_WALK_STOP; } return TSK_WALK_CONT; }
/* * file_walk action callback for ntfs * */ static uint8_t ifind_data_file_ntfs_act(TSK_FS_INFO * fs, DADDR_T addr, char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr) { if (addr == block) { tsk_printf("%" PRIuINUM "-%" PRIu32 "-%" PRIu16 "\n", curinode, curtype, curid); if (!(localflags & TSK_FS_IFIND_ALL)) { fs->close(fs); exit(0); } found = 1; } return TSK_WALK_CONT; }
// Find the inode that has allocated the specified block // // \param fs filesystem info structure defined in sleuthkit // \param lclflags traverse options defined in sleuthkit // \param blk the target block // // Return 0 if error, otherwise a pointer static MBA_IFIND_DATA_DATA* fs_ifind_data(TSK_FS_INFO * fs, TSK_FS_IFIND_FLAG_ENUM lclflags, TSK_DADDR_T blk) { MBA_IFIND_DATA_DATA* data; data = (MBA_IFIND_DATA_DATA*)malloc(sizeof(MBA_IFIND_DATA_DATA)); if(data == NULL) { printf("Cannot allocate memory\n"); return NULL; } memset(data, 0, sizeof(MBA_IFIND_DATA_DATA)); data->flags = lclflags; data->block = blk; if (fs->inode_walk(fs, fs->first_inum, fs->last_inum, TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC, ifind_data_act, data)) { free(data); return NULL; } /* If we did not find an inode yet, get the block's * flags so we can identify it as a meta data block */ if (!data->found) { TSK_FS_BLOCK *fs_block; if ((fs_block = tsk_fs_block_get(fs, NULL, blk)) != NULL) { if (fs_block->flags & TSK_FS_BLOCK_FLAG_META) { tsk_printf("Meta Data\n"); data->found = 1; } tsk_fs_block_free(fs_block); } } if (!data->found) { //tsk_printf("Inode not found\n"); free(data); return NULL; } return data; }
/* function used when -d is given ** ** keeps a count of unallocated blocks seen thus far ** ** If the specified block is allocated, an error is given, else the ** count of unalloc blocks is given ** ** This is called for all blocks (alloc and unalloc) */ static TSK_WALK_RET_ENUM count_dd_act(const TSK_FS_BLOCK * fs_block, void *ptr) { BLKCALC_DATA *data = (BLKCALC_DATA *) ptr; if (fs_block->flags & TSK_FS_BLOCK_FLAG_UNALLOC) data->uncnt++; if (data->count-- == 0) { if (fs_block->flags & TSK_FS_BLOCK_FLAG_UNALLOC) tsk_printf("%" PRIuDADDR "\n", data->uncnt); else printf ("ERROR: unit is allocated, it will not be in an blkls image\n"); data->found = 1; return TSK_WALK_STOP; } return TSK_WALK_CONT; }
/* Return 1 if block is not found, 0 if it was found, and -1 on error */ int8_t tsk_fs_blkcalc(TSK_FS_INFO * fs, TSK_FS_BLKCALC_FLAG_ENUM a_lclflags, TSK_DADDR_T a_cnt) { BLKCALC_DATA data; data.count = a_cnt; data.found = 0; if (a_lclflags == TSK_FS_BLKCALC_BLKLS) { if (tsk_fs_block_walk(fs, fs->first_block, fs->last_block, (TSK_FS_BLOCK_FLAG_UNALLOC | TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_CONT), count_blkls_act, &data)) return -1; } else if (a_lclflags == TSK_FS_BLKCALC_DD) { if (tsk_fs_block_walk(fs, fs->first_block, fs->last_block, (TSK_FS_BLOCK_FLAG_ALLOC | TSK_FS_BLOCK_FLAG_UNALLOC | TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_CONT), count_dd_act, &data)) return -1; } else if (a_lclflags == TSK_FS_BLKCALC_SLACK) { if (fs->inode_walk(fs, fs->first_inum, fs->last_inum, TSK_FS_META_FLAG_ALLOC, count_slack_inode_act, &data)) return -1; } if (data.found == 0) { tsk_printf("Block too large\n"); return 1; } else { return 0; } }
/* * file_walk action for non-ntfs */ static uint8_t ifind_data_file_act(TSK_FS_INFO * fs, DADDR_T addr, char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr) { /* Drop references to block zero (sparse) * This becomes an issue with fragments and looking for fragments * within the first block. They will be triggered by sparse * entries, even though the first block can not be allocated */ if (!addr) return TSK_WALK_CONT; if ((block >= addr) && (block < (addr + (size + fs->block_size - 1) / fs->block_size))) { tsk_printf("%" PRIuINUM "\n", curinode); if (!(localflags & TSK_FS_IFIND_ALL)) { fs->close(fs); exit(0); } found = 1; } return TSK_WALK_CONT; }
int MAIN(int argc, TSK_TCHAR ** argv) { TSK_FS_INFO *fs; TSK_IMG_INFO *img; TSK_TCHAR *fstype = NULL; TSK_TCHAR *imgtype = NULL; int ch; uint8_t type = 0; SSIZE_T imgoff = 0; progname = argv[0]; setlocale(LC_ALL, ""); while ((ch = getopt(argc, argv, _TSK_T("f:i:o:tvV"))) > 0) { switch (ch) { case _TSK_T('?'): default: TFPRINTF(stderr, _TSK_T("Invalid argument: %s\n"), argv[optind]); usage(); case _TSK_T('f'): fstype = optarg; if (TSTRCMP(fstype, _TSK_T("list")) == 0) { tsk_fs_print_types(stderr); exit(1); } break; case _TSK_T('i'): imgtype = optarg; if (TSTRCMP(imgtype, _TSK_T("list")) == 0) { tsk_img_print_types(stderr); exit(1); } break; case _TSK_T('o'): if ((imgoff = tsk_parse_offset(optarg)) == -1) { tsk_error_print(stderr); exit(1); } break; case _TSK_T('t'): type = 1; break; case _TSK_T('v'): tsk_verbose++; break; case _TSK_T('V'): tsk_print_version(stdout); exit(0); } } /* We need at least one more argument */ if (optind >= argc) { tsk_fprintf(stderr, "Missing image name\n"); usage(); } if ((img = tsk_img_open(imgtype, argc - optind, (const TSK_TCHAR **) &argv[optind])) == NULL) { tsk_error_print(stderr); exit(1); } if ((fs = tsk_fs_open(img, imgoff, fstype)) == NULL) { tsk_error_print(stderr); if (tsk_errno == TSK_ERR_FS_UNSUPTYPE) tsk_fs_print_types(stderr); img->close(img); exit(1); } if (type) { char *str = tsk_fs_get_type(fs->ftype); tsk_printf("%s\n", str); } else { if (fs->fsstat(fs, stdout)) { tsk_error_print(stderr); fs->close(fs); img->close(img); exit(1); } } fs->close(fs); img->close(img); exit(0); }
/* Return -1 for error, 0 if found, and 1 if not found */ int8_t tsk_fs_ifind_path(TSK_FS_INFO * fs, uint8_t lclflags, TSK_TCHAR * tpath, INUM_T * result) { char *cpath; IFIND_PATH_DATA ipd; localflags = lclflags; #ifdef TSK_WIN32 { size_t clen; UTF8 *ptr8; UTF16 *ptr16; int retval; clen = TSTRLEN(tpath) * 4; cpath = (char *) tsk_malloc(clen); if (cpath == NULL) { return -1; } ptr8 = (UTF8 *) cpath; ptr16 = (UTF16 *) tpath; retval = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &ptr16, (UTF16 *) & ptr16[TSTRLEN(tpath) + 1], &ptr8, (UTF8 *) ((uintptr_t) ptr8 + clen), TSKlenientConversion); if (retval != TSKconversionOK) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNICODE; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_ifind_path: Error converting path to UTF-8: %d", retval); free(cpath); return -1; } } #else cpath = tpath; #endif ipd.id = IFIND_PATH_DATA_ID; ipd.found = 0; ipd.badpath = 0; ipd.cur_dir = (char *) strtok_r(cpath, "/", &ipd.strtok_last); ipd.cur_attr = NULL; /* If there is no token, then only a '/' was given */ if (!(ipd.cur_dir)) { #ifdef TSK_WIN32 free(cpath); #endif *result = fs->root_inum; return 0; } /* If this is NTFS, ensure that we take out the attribute */ if (((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_NTFS_TYPE) && ((ipd.cur_attr = strchr(ipd.cur_dir, ':')) != NULL)) { *(ipd.cur_attr) = '\0'; ipd.cur_attr++; } if (tsk_verbose) tsk_fprintf(stderr, "Looking for %s\n", ipd.cur_dir); if (fs->dent_walk(fs, fs->root_inum, TSK_FS_DENT_FLAG_ALLOC | TSK_FS_DENT_FLAG_UNALLOC, ifind_path_act, (void *) &ipd)) { /* If we found files before the error was encountered, then * ignore it */ if (ipd.found == 0) { #ifdef TSK_WIN32 free(cpath); #endif return -1; } else { tsk_error_reset(); } } #ifdef TSK_WIN32 free(cpath); #endif if (1 == ipd.badpath) { if (tsk_verbose) tsk_fprintf(stderr, "Invalid path (%s is a file)\n", fs_dent->name); *result = 0; return 1; } else if (0 == ipd.found) { if (tsk_verbose) tsk_printf("File not found: %s\n", ipd.cur_dir); *result = 0; return 1; } *result = ipd.addr; return 0; }
/* * dent_walk for finding the inode based on path * * This is run from the main function and from this function when * the needed directory is found */ static uint8_t ifind_path_act(TSK_FS_INFO * fs, TSK_FS_DENT * fs_dent, void *ptr) { IFIND_PATH_DATA *ipd = (IFIND_PATH_DATA *) ptr; char *pname; if ((!ipd) || (ipd->id != IFIND_PATH_DATA_ID)) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "ifind_path_act: callback pointer is not IFIND_DATA_ID\n"); return TSK_WALK_ERROR; } /* This crashed because cur_dir was null, but I'm not sure how * it got that way, so this was added */ if (ipd->cur_dir == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "ifind: cur_dir is null: Please run with '-v' and send output to developers\n"); return TSK_WALK_ERROR; } /* * Check if this is the name that we are currently looking for, * as identified in 'cur_dir' * * All non-matches will return from these checks */ if (((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_EXT_TYPE) || ((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_FFS_TYPE)) { if (strcmp(fs_dent->name, ipd->cur_dir) != 0) { return TSK_WALK_CONT; } } /* NTFS gets a case insensitive comparison */ else if ((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_NTFS_TYPE) { if (strcasecmp(fs_dent->name, ipd->cur_dir) != 0) { return TSK_WALK_CONT; } /* ensure we have the right attribute name */ if (ipd->cur_attr != NULL) { int fail = 1; if (fs_dent->fsi) { TSK_FS_DATA *fs_data; for (fs_data = fs_dent->fsi->attr; fs_data != NULL; fs_data = fs_data->next) { if ((fs_data->flags & TSK_FS_DATA_INUSE) == 0) continue; if (strcasecmp(fs_data->name, ipd->cur_attr) == 0) { fail = 0; break; } } } if (fail) { tsk_printf("Attribute name (%s) not found in %s: %" PRIuINUM "\n", ipd->cur_attr, ipd->cur_dir, fs_dent->inode); return TSK_WALK_STOP; } } } /* FAT is a special case because we do case insensitive and we check * the short name */ else if ((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_FAT_TYPE) { if (strcasecmp(fs_dent->name, ipd->cur_dir) != 0) { if (strcasecmp(fs_dent->shrt_name, ipd->cur_dir) != 0) { return TSK_WALK_CONT; } } } /* Get the next directory or file name in the path */ pname = ipd->cur_dir; // save a copy of the current name pointer ipd->cur_dir = (char *) strtok_r(NULL, "/", &(ipd->strtok_last)); ipd->cur_attr = NULL; if (tsk_verbose) tsk_fprintf(stderr, "Found it (%s), now looking for %s\n", fs_dent->name, ipd->cur_dir); /* That was the last name in the path -- we found the file */ if (ipd->cur_dir == NULL) { //tsk_printf("%" PRIuINUM "\n", fs_dent->inode); ipd->found = 1; ipd->addr = fs_dent->inode; // if our only hit is an unallocated entry // then keep on looking -- this commonly happens with NTFS if (fs_dent->flags & TSK_FS_DENT_FLAG_UNALLOC) { ipd->cur_dir = pname; return TSK_WALK_CONT; } else { return TSK_WALK_STOP; } } /* if it is an NTFS image with an ADS in the name, then * break it up */ if (((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) == TSK_FS_INFO_TYPE_NTFS_TYPE) && ((ipd->cur_attr = strchr(ipd->cur_dir, ':')) != NULL)) { *(ipd->cur_attr) = '\0'; ipd->cur_attr++; } /* it is a directory so we can recurse */ if ((fs_dent->fsi->mode & TSK_FS_INODE_MODE_FMT) == TSK_FS_INODE_MODE_DIR) { if (fs->dent_walk(fs, fs_dent->inode, TSK_FS_DENT_FLAG_ALLOC | TSK_FS_DENT_FLAG_UNALLOC, ifind_path_act, (void *) ipd)) { return TSK_WALK_ERROR; } } /* The name was correct, but it was not a directory */ else { ipd->badpath = 1; } return TSK_WALK_STOP; }
/** * Read a specific number of blocks and print the contents to STDOUT * * @param fs File system to analyze * @param lclflags flags * @param addr Starting block address to read from * @param read_num_units Number of blocks to read * * @return 1 on error and 0 on success */ uint8_t tsk_fs_blkcat(TSK_FS_INFO * fs, TSK_FS_BLKCAT_FLAG_ENUM lclflags, TSK_DADDR_T addr, TSK_DADDR_T read_num_units) { char *buf; ssize_t cnt; int i; if (lclflags & TSK_FS_BLKCAT_STAT) { stats(fs); return 0; } if (addr + read_num_units - 1 > fs->last_block) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr ("tsk_fs_blkcat: requested size is larger than last block in image (%" PRIuDADDR ")", fs->last_block); return 1; } #ifdef TSK_WIN32 if (-1 == _setmode(_fileno(stdout), _O_BINARY)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_WRITE); tsk_error_set_errstr ("blkcat_lib: error setting stdout to binary: %s", strerror(errno)); return 1; } #endif if (lclflags & TSK_FS_BLKCAT_HTML) { tsk_printf("<html>\n"); tsk_printf("<head>\n"); tsk_printf("<title>Unit: %" PRIuDADDR " Size: %" PRIuOFF " bytes</title>\n", addr, read_num_units * fs->block_size); tsk_printf("</head>\n"); tsk_printf("<body>\n"); } if ((lclflags & TSK_FS_BLKCAT_HEX) && (lclflags & TSK_FS_BLKCAT_HTML)) tsk_printf("<table border=0>\n"); if ((buf = tsk_malloc(fs->block_size)) == NULL) return 1; for (i = 0; i < read_num_units; i++) { /* Read the block */ cnt = tsk_fs_read_block(fs, addr + i, buf, fs->block_size); if (cnt != fs->block_size) { if (cnt >= 0) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); } tsk_error_set_errstr("blkcat: Error reading block at %" PRIuDADDR, addr); return 1; } /* do a hexdump like printout */ if (lclflags & TSK_FS_BLKCAT_HEX) { TSK_OFF_T idx1, idx2; for (idx1 = 0; idx1 < fs->block_size; idx1 += 16) { /* Print the offset */ if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("<tr><td>%" PRIuOFF "</td>", i * fs->block_size + idx1); else tsk_printf("%" PRIuOFF "\t", i * fs->block_size + idx1); /* Print the hex */ for (idx2 = 0; idx2 < 16; idx2++) { if ((lclflags & TSK_FS_BLKCAT_HTML) && (0 == (idx2 % 4))) tsk_printf("<td>"); tsk_printf("%.2x", buf[idx2 + idx1] & 0xff); if (3 == (idx2 % 4)) { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("</td>"); else tsk_printf(" "); } } /* Print the ASCII */ tsk_printf("\t"); for (idx2 = 0; idx2 < 16; idx2++) { if ((lclflags & TSK_FS_BLKCAT_HTML) && (0 == (idx2 % 4))) tsk_printf("<td>"); if ((isascii((int) buf[idx2 + idx1])) && (!iscntrl((int) buf[idx2 + idx1]))) tsk_printf("%c", buf[idx2 + idx1]); else tsk_printf("."); if (3 == (idx2 % 4)) { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("</td>"); else tsk_printf(" "); } } if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("</tr>"); tsk_printf("\n"); } } /* print in all ASCII */ else if (lclflags & TSK_FS_BLKCAT_ASCII) { TSK_OFF_T idx; for (idx = 0; idx < fs->block_size; idx++) { if ((isprint((int) buf[idx])) || (buf[idx] == '\t')) { tsk_printf("%c", buf[idx]); } else if ((buf[idx] == '\n') || (buf[idx] == '\r')) { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("<br>"); tsk_printf("%c", buf[idx]); } else tsk_printf("."); } } /* print raw */ else { if (fwrite(buf, fs->block_size, 1, stdout) != 1) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_WRITE); tsk_error_set_errstr ("blkcat_lib: error writing to stdout: %s", strerror(errno)); free(buf); return 1; } } } free(buf); if (lclflags & TSK_FS_BLKCAT_HEX) { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("</table>\n"); else tsk_printf("\n"); } else if (lclflags & TSK_FS_BLKCAT_ASCII) { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("<br>"); tsk_printf("\n"); } else { if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("<br>"); } if (lclflags & TSK_FS_BLKCAT_HTML) tsk_printf("</body>\n</html>\n"); return 0; }
int MAIN(int argc, TSK_TCHAR ** argv) { TSK_TCHAR *imgtype = NULL; TSK_TCHAR *fstype = NULL; TSK_FS_INFO *fs; TSK_IMG_INFO *img; int ch; TSK_TCHAR *cp; extern int optind; DADDR_T block = 0; /* the block to find */ INUM_T parinode = 0; TSK_TCHAR *path = NULL; SSIZE_T imgoff = 0; progname = argv[0]; setlocale(LC_ALL, ""); localflags = 0; while ((ch = getopt(argc, argv, _TSK_T("ad:f:i:ln:o:p:vVz:"))) > 0) { switch (ch) { case _TSK_T('a'): localflags |= TSK_FS_IFIND_ALL; break; case _TSK_T('d'): if (localflags & (TSK_FS_IFIND_PAR | TSK_FS_IFIND_PATH)) { tsk_fprintf(stderr, "error: only one address type can be given\n"); usage(); } localflags |= TSK_FS_IFIND_DATA; block = TSTRTOULL(optarg, &cp, 0); if (*cp || *cp == *optarg) { TFPRINTF(stderr, _TSK_T("Invalid block address: %s\n"), optarg); usage(); } break; case _TSK_T('f'): fstype = optarg; if (TSTRCMP(fstype, _TSK_T("list")) == 0) { tsk_fs_print_types(stderr); exit(1); } break; case _TSK_T('i'): imgtype = optarg; if (TSTRCMP(imgtype, _TSK_T("list")) == 0) { tsk_img_print_types(stderr); exit(1); } break; case _TSK_T('l'): localflags |= TSK_FS_IFIND_PAR_LONG; break; case _TSK_T('n'): { size_t len; if (localflags & (TSK_FS_IFIND_PAR | TSK_FS_IFIND_DATA)) { tsk_fprintf(stderr, "error: only one address type can be given\n"); usage(); } localflags |= TSK_FS_IFIND_PATH; len = (TSTRLEN(optarg) + 1) * sizeof(TSK_TCHAR); if ((path = (TSK_TCHAR *) tsk_malloc(len)) == NULL) { tsk_error_print(stderr); exit(1); } TSTRNCPY(path, optarg, TSTRLEN(optarg) + 1); break; } case 'o': if ((imgoff = tsk_parse_offset(optarg)) == -1) { tsk_error_print(stderr); exit(1); } break; case 'p': if (localflags & (TSK_FS_IFIND_PATH | TSK_FS_IFIND_DATA)) { tsk_fprintf(stderr, "error: only one address type can be given\n"); usage(); } localflags |= TSK_FS_IFIND_PAR; if (tsk_parse_inum(optarg, &parinode, NULL, NULL, NULL)) { TFPRINTF(stderr, _TSK_T("Invalid inode address: %s\n"), optarg); usage(); } break; case 'v': tsk_verbose++; break; case 'V': tsk_print_version(stdout); exit(0); case 'z': { TSK_TCHAR envstr[32]; TSNPRINTF(envstr, 32, _TSK_T("TZ=%s"), optarg); if (0 != PUTENV(envstr)) { tsk_fprintf(stderr, "error setting environment"); exit(1); } /* we should be checking this somehow */ TZSET(); break; } case '?': default: tsk_fprintf(stderr, "Invalid argument: %s\n", argv[optind]); usage(); } } /* We need at least one more argument */ if (optind >= argc) { tsk_fprintf(stderr, "Missing image name\n"); if (path) free(path); usage(); } if (0 == (localflags & (TSK_FS_IFIND_PATH | TSK_FS_IFIND_DATA | TSK_FS_IFIND_PAR))) { tsk_fprintf(stderr, "-d, -n, or -p must be given\n"); usage(); } if ((img = tsk_img_open(imgtype, argc - optind, (const TSK_TCHAR **) &argv[optind])) == NULL) { tsk_error_print(stderr); if (path) free(path); exit(1); } if ((fs = tsk_fs_open(img, imgoff, fstype)) == NULL) { tsk_error_print(stderr); if (tsk_errno == TSK_ERR_FS_UNSUPTYPE) tsk_fs_print_types(stderr); img->close(img); if (path) free(path); exit(1); } if (localflags & TSK_FS_IFIND_DATA) { if (block > fs->last_block) { tsk_fprintf(stderr, "Block %" PRIuDADDR " is larger than last block in image (%" PRIuDADDR ")\n", block, fs->last_block); fs->close(fs); img->close(img); exit(1); } else if (block == 0) { tsk_printf("Inode not found\n"); fs->close(fs); img->close(img); exit(1); } if (tsk_fs_ifind_data(fs, localflags, block)) { tsk_error_print(stderr); fs->close(fs); img->close(img); exit(1); } } else if (localflags & TSK_FS_IFIND_PAR) { if ((fs->ftype & TSK_FS_INFO_TYPE_FS_MASK) != TSK_FS_INFO_TYPE_NTFS_TYPE) { tsk_fprintf(stderr, "-p works only with NTFS file systems\n"); fs->close(fs); img->close(img); exit(1); } else if (parinode > fs->last_inum) { tsk_fprintf(stderr, "Meta data %" PRIuINUM " is larger than last MFT entry in image (%" PRIuINUM ")\n", parinode, fs->last_inum); fs->close(fs); img->close(img); exit(1); } if (tsk_fs_ifind_par(fs, localflags, parinode)) { tsk_error_print(stderr); fs->close(fs); img->close(img); exit(1); } } else if (localflags & TSK_FS_IFIND_PATH) { int retval; INUM_T inum; if (-1 == (retval = tsk_fs_ifind_path(fs, localflags, path, &inum))) { tsk_error_print(stderr); fs->close(fs); img->close(img); free(path); exit(1); } free(path); if (retval == 1) tsk_printf("File not found\n"); else tsk_printf("%" PRIuINUM "\n", inum); } fs->close(fs); img->close(img); exit(0); }
static void print_stats(const TSK_VS_INFO * vs) { tsk_printf("%s\n", tsk_vs_type_toname(vs->vstype)); return; }
// XXX([email protected]): had better fix the comment // find file of the given inode // // \param fs filesystem info structure defined in sleuthkit // \param lclflags traverse options defined in sleuthkit // \param a_inode the inode of the file // \param type filesystem type number // \param type_used don't know what it is, just give a 0(XXX) // \param id the id of file attribute that the inode refers // \param id_used don't know what it is, just give a 0(XXX) // \param flags traverse options difned in sleuthkit // // Return 0 if error, otherwise a pointer static MBA_FFIND_DATA* fs_ffind(TSK_FS_INFO * fs, TSK_FS_FFIND_FLAG_ENUM lclflags, TSK_INUM_T a_inode, TSK_FS_ATTR_TYPE_ENUM type, uint8_t type_used, uint16_t id, uint8_t id_used, TSK_FS_DIR_WALK_FLAG_ENUM flags) { MBA_FFIND_DATA* data=(MBA_FFIND_DATA*)malloc(sizeof(MBA_FFIND_DATA)); char* orphan =NULL; int size = 0; if(data == NULL) { printf("Cannot allocate memory\n"); return NULL; } data->found = 0; data->flags = lclflags; data->inode = a_inode; utarray_new(data->filenames, &ut_str_icd); /* Since we start the walk on the root inode, then this will not show ** up in the above functions, so do it now */ if (data->inode == fs->root_inum) { if (flags & TSK_FS_DIR_WALK_FLAG_ALLOC) { //tsk_printf("/\n"); data->found = 1; if (!(lclflags & TSK_FS_FFIND_ALL)) return data; } } if (TSK_FS_TYPE_ISNTFS(fs->ftype)) { if (ntfs_find_file(fs, data->inode, type, type_used, id, id_used, flags, find_file_act, data)) return NULL; } else { if (tsk_fs_dir_walk(fs, fs->root_inum, flags, find_file_act, data)) return NULL; } if (data->found == 0) { /* With FAT, we can at least give the name of the file and call * it orphan */ if (TSK_FS_TYPE_ISFAT(fs->ftype)) { TSK_FS_FILE *fs_file = tsk_fs_file_open_meta(fs, NULL, data->inode); if ((fs_file != NULL) && (fs_file->meta != NULL) && (fs_file->meta->name2 != NULL)) { //if (fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC) // tsk_printf("* "); //tsk_printf("%s/%s\n", TSK_FS_ORPHAN_STR, // fs_file->meta->name2->name); //Added Ophan file into file list size = strlen(TSK_FS_ORPHAN_STR) + strlen(fs_file->meta->name2->name)+2; orphan = (char*)malloc(size); if(orphan == NULL) { printf("Cannot allocate memory\n"); }else { snprintf(orphan, size, "%s/%s", TSK_FS_ORPHAN_STR,fs_file->meta->name2->name); utarray_push_back(data->filenames, orphan ); } } if (fs_file) tsk_fs_file_close(fs_file); } else { tsk_printf("File name not found for inode\n"); } } return data; }
/* inode walk call back for tsk_fs_ifind_par to find unallocated files * based on parent directory */ static TSK_WALK_RET_ENUM ifind_par_act(TSK_FS_FILE * fs_file, void *ptr) { IFIND_PAR_DATA *data = (IFIND_PAR_DATA *) ptr; TSK_FS_META_NAME_LIST *fs_name_list; /* go through each file name attribute for this file */ fs_name_list = fs_file->meta->name2; while (fs_name_list) { /* we found a file that has the target parent directory. * Make a FS_NAME structure and print it. */ if (fs_name_list->par_inode == data->parinode) { int i, cnt; uint8_t printed; TSK_FS_NAME *fs_name; if ((fs_name = tsk_fs_name_alloc(256, 0)) == NULL) return TSK_WALK_ERROR; /* Fill in the basics of the fs_name entry * so we can print in the fls formats */ fs_name->meta_addr = fs_file->meta->addr; fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC; strncpy(fs_name->name, fs_name_list->name, fs_name->name_size); // now look for the $Data and $IDXROOT attributes fs_file->name = fs_name; printed = 0; // cycle through the 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; if ((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_DATA) || (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_IDXROOT)) { if (data->flags & TSK_FS_IFIND_PAR_LONG) { tsk_fs_name_print_long(stdout, fs_file, NULL, fs_file->fs_info, fs_attr, 0, 0); tsk_printf("\n"); } else { tsk_fs_name_print(stdout, fs_file, NULL, fs_file->fs_info, fs_attr, 0); tsk_printf("\n"); } printed = 1; } } // if there were no attributes, print what we got if (printed == 0) { if (data->flags & TSK_FS_IFIND_PAR_LONG) { tsk_fs_name_print_long(stdout, fs_file, NULL, fs_file->fs_info, NULL, 0, 0); tsk_printf("\n"); } else { tsk_fs_name_print(stdout, fs_file, NULL, fs_file->fs_info, NULL, 0); tsk_printf("\n"); } } tsk_fs_name_free(fs_name); data->found = 1; } fs_name_list = fs_name_list->next; } return TSK_WALK_CONT; }
/** * \internal * Print block statistics to stdout * * @param fs File system to analyze */ static void stats(TSK_FS_INFO * fs) { tsk_printf("%d: Size of Addressable Unit\n", fs->block_size); }
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; int ch; uint8_t type = 0; TSK_TCHAR **argv; unsigned int ssize = 0; TSK_TCHAR *cp; #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, ""); while ((ch = GETOPT(argc, argv, _TSK_T("b:f:i:o:tvV"))) > 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('o'): if ((imgaddr = tsk_parse_offset(OPTARG)) == -1) { tsk_error_print(stderr); exit(1); } break; case _TSK_T('t'): type = 1; break; case _TSK_T('v'): tsk_verbose++; break; case _TSK_T('V'): tsk_version_print(stdout); exit(0); } } /* We need at least one more argument */ if (OPTIND >= argc) { tsk_fprintf(stderr, "Missing image name\n"); usage(); } 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); } 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); } if (type) { tsk_printf("%s\n", tsk_fs_type_toname(fs->ftype)); } else { if (fs->fsstat(fs, stdout)) { tsk_error_print(stderr); fs->close(fs); img->close(img); exit(1); } } fs->close(fs); img->close(img); exit(0); }