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_DADDR_T addr = 0; TSK_TCHAR *cp; TSK_DADDR_T read_num_units; /* Number of data units */ int usize = 0; /* Length of each data unit */ int ch; char format = 0; extern int OPTIND; 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, ""); while ((ch = GETOPT(argc, argv, _TSK_T("ab:f:hi:o:su:vVw"))) > 0) { switch (ch) { case _TSK_T('a'): format |= TSK_FS_BLKCAT_ASCII; break; 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, BLKLS_TYPE) == 0) { fstype = TSK_FS_TYPE_RAW; } else if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) { tsk_fprintf(stderr, "\t%" PRIttocTSK " (Unallocated Space)\n", BLKLS_TYPE); tsk_fs_type_print(stderr); exit(1); } else { 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('h'): format |= TSK_FS_BLKCAT_HEX; 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('s'): format |= TSK_FS_BLKCAT_STAT; break; case _TSK_T('u'): usize = TSTRTOUL(OPTARG, &cp, 0); if (*cp || cp == OPTARG) { TFPRINTF(stderr, _TSK_T("Invalid block size: %s\n"), OPTARG); usage(); } break; case _TSK_T('v'): tsk_verbose++; break; case _TSK_T('V'): tsk_version_print(stdout); exit(0); break; case _TSK_T('w'): format |= TSK_FS_BLKCAT_HTML; break; case _TSK_T('?'): default: TFPRINTF(stderr, _TSK_T("Invalid argument: %s\n"), argv[OPTIND]); usage(); } } if (format & TSK_FS_BLKCAT_STAT) { if (OPTIND == argc) usage(); if (format & (TSK_FS_BLKCAT_HTML | TSK_FS_BLKCAT_ASCII | TSK_FS_BLKCAT_HEX)) { tsk_fprintf(stderr, "NOTE: Additional flags will be ignored\n"); } } /* We need at least two more arguments */ else if (OPTIND + 1 >= argc) { tsk_fprintf(stderr, "Missing image name and/or address\n"); usage(); } if ((format & TSK_FS_BLKCAT_ASCII) && (format & TSK_FS_BLKCAT_HEX)) { tsk_fprintf(stderr, "Ascii and Hex flags can not be used together\n"); usage(); } /* We need to figure out if there is a length argument... */ /* Check out the second argument from the end */ /* default number of units is 1 */ read_num_units = 1; /* Get the block address */ if (format & TSK_FS_BLKCAT_STAT) { 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 { addr = TSTRTOULL(argv[argc - 2], &cp, 0); if (*cp || *cp == *argv[argc - 2]) { /* Not a number, so it is the image name and we do not have a length */ addr = TSTRTOULL(argv[argc - 1], &cp, 0); if (*cp || *cp == *argv[argc - 1]) { TFPRINTF(stderr, _TSK_T("Invalid block address: %s\n"), argv[argc - 1]); usage(); } 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 got a number, so take the length as well while we are at it */ read_num_units = TSTRTOULL(argv[argc - 1], &cp, 0); if (*cp || *cp == *argv[argc - 1]) { TFPRINTF(stderr, _TSK_T("Invalid size: %s\n"), argv[argc - 1]); usage(); } else if (read_num_units <= 0) { tsk_fprintf(stderr, "Invalid size: %" PRIuDADDR "\n", read_num_units); usage(); } if ((img = tsk_img_open(argc - OPTIND - 2, &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); } } } /* open the file */ if ((fs = tsk_fs_open_img(img, imgaddr * img->sector_size, fstype)) == NULL) { tsk_error_print(stderr); if (tsk_errno == TSK_ERR_FS_UNSUPTYPE) tsk_fs_type_print(stderr); img->close(img); exit(1); } /* Set the default size if given */ if ((usize != 0) && (TSK_FS_TYPE_ISRAW(fs->ftype) || TSK_FS_TYPE_ISSWAP(fs->ftype))) { TSK_DADDR_T sectors; int orig_dsize, new_dsize; if (usize % 512) { tsk_fprintf(stderr, "New data unit size not a multiple of 512 (%d)\n", usize); usage(); } /* We need to do some math to update the block_count value */ /* Get the original number of sectors */ orig_dsize = fs->block_size / 512; sectors = fs->block_count * orig_dsize; /* Convert that to the new size */ new_dsize = usize / 512; fs->block_count = sectors / new_dsize; if (sectors % new_dsize) fs->block_count++; fs->last_block = fs->block_count - 1; fs->block_size = usize; } if (addr > fs->last_block) { tsk_fprintf(stderr, "Data unit address too large for image (%" PRIuDADDR ")\n", fs->last_block); fs->close(fs); img->close(img); exit(1); } if (addr < fs->first_block) { tsk_fprintf(stderr, "Data unit address too small for image (%" PRIuDADDR ")\n", fs->first_block); fs->close(fs); img->close(img); exit(1); } if (tsk_fs_blkcat(fs, (TSK_FS_BLKCAT_FLAG_ENUM) format, addr, read_num_units)) { tsk_error_print(stderr); fs->close(fs); img->close(img); exit(1); } fs->close(fs); img->close(img); exit(0); }
/** * \ingroup fslib * Tries to process data in a disk image at a given offset as a file system. * Returns a structure that can be used for analysis and reporting. * * @param a_img_info Disk image to analyze * @param a_offset Byte offset to start analyzing from * @param a_ftype Type of file system (or autodetect) * * @return NULL on error */ TSK_FS_INFO * tsk_fs_open_img(TSK_IMG_INFO * a_img_info, TSK_OFF_T a_offset, TSK_FS_TYPE_ENUM a_ftype) { if (a_img_info == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_open_img: Null image handle"); return NULL; } /* We will try different file systems ... * We need to try all of them in case more than one matches */ if (a_ftype == TSK_FS_TYPE_DETECT) { TSK_FS_INFO *fs_info, *fs_set = NULL; char *set = NULL; if (tsk_verbose) tsk_fprintf(stderr, "fsopen: Auto detection mode at offset %" PRIuOFF "\n", a_offset); if ((fs_info = ntfs_open(a_img_info, a_offset, TSK_FS_TYPE_NTFS_DETECT, 1)) != NULL) { set = "NTFS"; fs_set = fs_info; } else { tsk_error_reset(); } if ((fs_info = fatfs_open(a_img_info, a_offset, TSK_FS_TYPE_FAT_DETECT, 1)) != NULL) { if (set == NULL) { set = "FAT"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "FAT or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ext2fs_open(a_img_info, a_offset, TSK_FS_TYPE_EXT_DETECT, 1)) != NULL) { if (set == NULL) { set = "EXT2/3"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "EXT2/3 or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ffs_open(a_img_info, a_offset, TSK_FS_TYPE_FFS_DETECT)) != NULL) { if (set == NULL) { set = "UFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "UFS or %s", set); return NULL; } } else { tsk_error_reset(); } #if TSK_USE_HFS if ((fs_info = hfs_open(a_img_info, a_offset, TSK_FS_TYPE_HFS_DETECT, 1)) != NULL) { if (set == NULL) { set = "HFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "HFS or %s", set); return NULL; } } else { tsk_error_reset(); } #endif if ((fs_info = iso9660_open(a_img_info, a_offset, TSK_FS_TYPE_ISO9660_DETECT, 1)) != NULL) { if (set != NULL) { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "ISO9660 or %s", set); return NULL; } fs_set = fs_info; } else { tsk_error_reset(); } if (fs_set == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; tsk_errstr[0] = '\0'; tsk_errstr2[0] = '\0'; return NULL; } return fs_set; } else { if (TSK_FS_TYPE_ISNTFS(a_ftype)) return ntfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISFAT(a_ftype)) return fatfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISFFS(a_ftype)) return ffs_open(a_img_info, a_offset, a_ftype); else if (TSK_FS_TYPE_ISEXT(a_ftype)) return ext2fs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISHFS(a_ftype)) return hfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISISO9660(a_ftype)) return iso9660_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISRAW(a_ftype)) return rawfs_open(a_img_info, a_offset); else if (TSK_FS_TYPE_ISSWAP(a_ftype)) return swapfs_open(a_img_info, a_offset); else { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNSUPTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "%X", (int) a_ftype); return NULL; } } }
/** * \ingroup fslib * Tries to process data in a disk image at a given offset as a file system. * Returns a structure that can be used for analysis and reporting. * * @param a_img_info Disk image to analyze * @param a_offset Byte offset to start analyzing from * @param a_ftype Type of file system (or autodetect) * * @return NULL on error */ TSK_FS_INFO * tsk_fs_open_img(TSK_IMG_INFO * a_img_info, TSK_OFF_T a_offset, TSK_FS_TYPE_ENUM a_ftype) { TSK_FS_INFO *fs_info; const struct { char* name; TSK_FS_INFO* (*open)(TSK_IMG_INFO*, TSK_OFF_T, TSK_FS_TYPE_ENUM, uint8_t); TSK_FS_TYPE_ENUM type; } FS_OPENERS[] = { { "NTFS", ntfs_open, TSK_FS_TYPE_NTFS_DETECT }, { "FAT", fatfs_open, TSK_FS_TYPE_FAT_DETECT }, { "EXT2/3/4", ext2fs_open, TSK_FS_TYPE_EXT_DETECT }, { "UFS", ffs_open, TSK_FS_TYPE_FFS_DETECT }, { "YAFFS2", yaffs2_open, TSK_FS_TYPE_YAFFS2_DETECT }, #if TSK_USE_HFS { "HFS", hfs_open, TSK_FS_TYPE_HFS_DETECT }, #endif { "ISO9660", iso9660_open, TSK_FS_TYPE_ISO9660_DETECT } }; if (a_img_info == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr("tsk_fs_open_img: Null image handle"); return NULL; } /* We will try different file systems ... * We need to try all of them in case more than one matches */ if (a_ftype == TSK_FS_TYPE_DETECT) { unsigned long i; const char *name_first = ""; TSK_FS_INFO *fs_first = NULL; if (tsk_verbose) tsk_fprintf(stderr, "fsopen: Auto detection mode at offset %" PRIuOFF "\n", a_offset); for (i = 0; i < sizeof(FS_OPENERS)/sizeof(FS_OPENERS[0]); ++i) { if ((fs_info = FS_OPENERS[i].open( a_img_info, a_offset, FS_OPENERS[i].type, 1)) != NULL) { // fs opens as type i if (fs_first == NULL) { // first success opening fs name_first = FS_OPENERS[i].name; fs_first = fs_info; } else { // second success opening fs, which means we // cannot autodetect the fs type and must give up fs_first->close(fs_first); fs_info->close(fs_info); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNKTYPE); tsk_error_set_errstr( "%s or %s", FS_OPENERS[i].name, name_first); return NULL; } } else { // fs does not open as type i tsk_error_reset(); } } if (fs_first == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNKTYPE); } return fs_first; } else if (TSK_FS_TYPE_ISNTFS(a_ftype)) { return ntfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISFAT(a_ftype)) { return fatfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISFFS(a_ftype)) { return ffs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISEXT(a_ftype)) { return ext2fs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISHFS(a_ftype)) { return hfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISISO9660(a_ftype)) { return iso9660_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISRAW(a_ftype)) { return rawfs_open(a_img_info, a_offset); } else if (TSK_FS_TYPE_ISSWAP(a_ftype)) { return swapfs_open(a_img_info, a_offset); } else if (TSK_FS_TYPE_ISYAFFS2(a_ftype)) { return yaffs2_open(a_img_info, a_offset, a_ftype, 0); } tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNSUPTYPE); tsk_error_set_errstr("%X", (int) a_ftype); return NULL; }