📄 hfs.c
字号:
if (uni_len > 255) { tsk_errno = TSK_ERR_FS_INODE_COR; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_read_thread_record: invalid string length (%" PRIu16 ")", uni_len); return 1; } if (hfs_checked_read_random(fs, (char *) thread->name.unicode, uni_len * 2, addr + 10)) return 1; return 0;}/** \internal * Read a catalog record into a local data structure. This reads the * correct amount, depending on if it is a file or folder. * @param hfs File system being analyzed * @param off Byte offset (in disk) of record * @param record [out] Structure to read data into * @returns 1 on error */uint8_thfs_read_file_folder_record(HFS_INFO * hfs, TSK_OFF_T off, hfs_file_folder * record){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); memset(record, 0, sizeof(hfs_file_folder)); if (hfs_checked_read_random(fs, (char *) record, 2, off)) return 1; if (tsk_getu16(fs->endian, record->file.rec_type) == HFS_FOLDER_RECORD) { if (hfs_checked_read_random(fs, ((char *) record) + 2, sizeof(hfs_folder) - 2, off + 2)) return 1; } else if (tsk_getu16(fs->endian, record->file.rec_type) == HFS_FILE_RECORD) { if (hfs_checked_read_random(fs, ((char *) record) + 2, sizeof(hfs_file) - 2, off + 2)) return 1; } else { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_read_file_folder_record: unexpected record type %" PRIu16, tsk_getu16(fs->endian, record->file.rec_type)); return 1; } return 0;}/** \internal * Lookup an entry in the catalog file and save it into the entry * data structure. * @param hfs File system being analyzed * @param inum Address (cnid) of file to open * @param entry [out] Structure to read data into * @returns 1 on error or not found, 0 on success. Check tsk_errno * to differentiate between error and not found. */uint8_thfs_catalog_lookup(HFS_INFO * hfs, TSK_INUM_T inum, HFS_ENTRY * entry){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); hfs_cat_key key; /* current catalog key */ uint32_t cnid; /* catalog node ID of the entry (= inum) */ hfs_thread thread; /* thread record */ hfs_file_folder record; /* file/folder record */ TSK_OFF_T off; char fname[HFS_MAXNAMLEN + 1]; uint32_t *temp_32ptr; tsk_error_reset(); if (tsk_verbose) tsk_fprintf(stderr, "hfs_catalog_lookup: called for inum %" PRIuINUM "\n", inum); /* first look up the thread record for the item we're searching for */ /* set up the thread record key */ cnid = (uint32_t) inum; memset((char *) &key, 0, sizeof(hfs_cat_key)); temp_32ptr = (uint32_t *) (key.parent_cnid); // @@@ Why is this needed, cnid is inum, which is local ordering... // I think the goal is to put it back into BE ordering, but that seems to not work.. *temp_32ptr = tsk_getu32(fs->endian, (char *) &cnid); /* look up the thread record */ off = hfs_find_catalog_record(hfs, &key); if (off == 0) return 1; /* read the thread record */ if (hfs_read_thread_record(hfs, off, &thread)) return 1; if (hfs_uni2ascii(fs, thread.name.unicode, tsk_getu16(fs->endian, thread.name.length), fname, HFS_MAXNAMLEN + 1)) return 1; if (tsk_verbose) fprintf(stderr, "hfs_catalog_lookup: parent cnid %" PRIu32 " node name (%" PRIu16 ") %s\n", tsk_getu32(fs->endian, thread.parent_cnid), tsk_getu16(fs->endian, thread.name.length), fname); /* now look up the actual file/folder record */ /* build key */ memset((char *) &key, 0, sizeof(hfs_cat_key)); memcpy(((char *) &key) + 2, ((char *) &thread) + 4, sizeof(hfs_cat_key) - 2); /* look up the record */ off = hfs_find_catalog_record(hfs, &key); if (off == 0) return 1; /* read the record */ if (hfs_read_file_folder_record(hfs, off, &record)) return 1; /* these memcpy can be gotten rid of, really */ if (tsk_getu16(fs->endian, record.file.rec_type) == HFS_FOLDER_RECORD) { if (tsk_verbose) fprintf(stderr, "hfs_catalog_lookup: found folder record valence %" PRIu32 ", cnid %" PRIu32 "\n", tsk_getu32(fs->endian, record.folder.valence), tsk_getu32(fs->endian, record.folder.cnid)); memcpy((char *) &entry->cat, (char *) &record, sizeof(hfs_folder)); } else if (tsk_getu16(fs->endian, record.file.rec_type) == HFS_FILE_RECORD) { if (tsk_verbose) fprintf(stderr, "hfs_catalog_lookup: found file record cnid %" PRIu32 "\n", tsk_getu32(fs->endian, record.file.cnid)); memcpy((char *) &entry->cat, (char *) &record, sizeof(hfs_file)); } /* other cases already caught by hfs_read_file_folder_record */ memcpy((char *) &entry->thread, (char *) &thread, sizeof(hfs_thread)); entry->flags |= TSK_FS_META_FLAG_ALLOC; /// @@@ What about USED, etc.? entry->inum = inum; if (tsk_verbose) tsk_fprintf(stderr, "hfs_catalog_lookup exited\n"); return 0;}/* get the catalog file header node and cache it. This will be useful for * searching later * returns 0 on success, 1 on failure; sets up to error string 2 */static uint8_thfs_catalog_get_header(HFS_INFO * hfs){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); int i; hfs_btree_node node; hfs_sb *sb = hfs->fs; TSK_DADDR_T r_offs; hfs_ext_desc *h; tsk_error_reset(); if (tsk_verbose) tsk_fprintf(stderr, "hfs_catalog_get_header: called\n"); /* already got it */ if (hfs->hdr) return 0; hfs->hdr = (hfs_btree_header_record *) tsk_malloc(sizeof(hfs_btree_header_record)); if (hfs->hdr == NULL) return 1; /* find first extent with data in it */ i = 0; h = sb->cat_file.extents; while (!(tsk_getu32(fs->endian, h[i].blk_cnt))) i++; /* TODO this "find first extent" is unchecked */ r_offs = tsk_getu32(fs->endian, h[i].start_blk) * fs->block_size; if (hfs_checked_read_random(fs, (char *) &node, sizeof(node), r_offs)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_catalog_get_header: reading catalog header node at %" PRIuDADDR, r_offs); return 1; } if (node.kind != HFS_BTREE_HEADER_NODE) { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_catalog_get_header: node zero at %" PRIuDADDR " is incorrect type (%" PRIu8 ")", r_offs, node.kind); return 1; } r_offs += sizeof(node); /* get header node of btree */ if (hfs_checked_read_random(fs, (char *) hfs->hdr, sizeof(hfs_btree_header_record), r_offs)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_catalog_get_header: reading catalog header at %" PRIuDADDR, r_offs); return 1; } return 0;}/* hfs_load_blockmap - This function will allocate a bitmap of blocks which * are allocated. */static inthfs_load_blockmap(HFS_INFO * hfs){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); hfs_ext_desc *extents; int i; uint8_t *ptr; uint32_t bytes_remaining; if (tsk_verbose) tsk_fprintf(stderr, "hfs_load_blockmap: called\n"); /* Note: the allocation file can be larger than the number of bytes computed below. According to TN1150, all extra bits must be set to 0. We avoid storing those empty bits; a consistency checker may want to actually load the whole allocation file and check that these bits are in fact empty. */ hfs->block_map_size = (uint32_t) roundup(fs->block_count / 8, fs->block_size); if ((hfs->block_map = (uint8_t *) tsk_malloc(hfs->block_map_size)) == NULL) return 1; memset(hfs->block_map, 0, hfs->block_map_size); extents = hfs_ext_find_extent_record(hfs, HFS_ALLOCATION_FILE_ID, hfs->fs->alloc_file.extents); if (extents == NULL) { tsk_fprintf(stderr, "hfs_load_blockmap: failed to find extents for allocation file\n"); return 1; } i = 0; ptr = hfs->block_map; bytes_remaining = hfs->block_map_size; while (bytes_remaining > 0) { uint32_t blocks; uint32_t bytes; TSK_OFF_T offset; blocks = tsk_getu32(fs->endian, extents[i].blk_cnt); if (blocks == 0) { tsk_fprintf(stderr, "hfs_load_blockmap: ran out of data for allocation file\n"); free(extents); return 1; } bytes = (bytes_remaining < blocks * fs->block_size) ? bytes_remaining : blocks * fs->block_size; offset = (TSK_OFF_T) tsk_getu32(fs->endian, extents[i].start_blk) * fs->block_size; if (hfs_checked_read_random(fs, (char *) ptr, bytes, offset)) { free(extents); return 1; } bytes_remaining -= bytes; ptr += bytes; } free(extents); return 0;}static TSK_FS_META_MODE_ENUMhfsmode2tskmode(uint16_t a_mode){ TSK_FS_META_MODE_ENUM mode = 0; if (a_mode & HFS_IN_ISUID) mode |= TSK_FS_META_MODE_ISUID; if (a_mode & HFS_IN_ISGID) mode |= TSK_FS_META_MODE_ISGID; if (a_mode & HFS_IN_ISVTX) mode |= TSK_FS_META_MODE_ISVTX; if (a_mode & HFS_IN_IRUSR) mode |= TSK_FS_META_MODE_IRUSR; if (a_mode & HFS_IN_IWUSR) mode |= TSK_FS_META_MODE_IWUSR; if (a_mode & HFS_IN_IXUSR) mode |= TSK_FS_META_MODE_IXUSR; if (a_mode & HFS_IN_IRGRP) mode |= TSK_FS_META_MODE_IRGRP; if (a_mode & HFS_IN_IWGRP) mode |= TSK_FS_META_MODE_IWGRP; if (a_mode & HFS_IN_IXGRP) mode |= TSK_FS_META_MODE_IXGRP; if (a_mode & HFS_IN_IROTH) mode |= TSK_FS_META_MODE_IROTH; if (a_mode & HFS_IN_IWOTH) mode |= TSK_FS_META_MODE_IWOTH; if (a_mode & HFS_IN_IXOTH) mode |= TSK_FS_META_MODE_IXOTH; return mode;}static TSK_FS_META_TYPE_ENUMhfsmode2tskmetatype(uint16_t a_mode){ switch (a_mode & HFS_IN_IFMT) { case HFS_IN_IFIFO: return TSK_FS_META_TYPE_FIFO; case HFS_IN_IFCHR: return TSK_FS_META_TYPE_CHR; case HFS_IN_IFDIR: return TSK_FS_META_TYPE_DIR; case HFS_IN_IFBLK: return TSK_FS_META_TYPE_BLK; case HFS_IN_IFREG: return TSK_FS_META_TYPE_REG; case HFS_IN_IFLNK: return TSK_FS_META_TYPE_LNK; case HFS_IN_IFSOCK: return TSK_FS_META_TYPE_SOCK; case HFS_IFWHT: return TSK_FS_META_TYPE_WHT; case HFS_IFXATTR: return TSK_FS_META_TYPE_UNDEF; default: /* error */ return TSK_FS_META_TYPE_UNDEF; }}/* * Copy the inode into the generic structure * Returns 1 on error. */uint8_thfs_dinode_copy(HFS_INFO * hfs, HFS_ENTRY * entry, TSK_FS_META * fs_inode){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & hfs->fs_info; if (tsk_verbose) tsk_fprintf(stderr, "hfs_dinode_copy: called\n"); fs_inode->attr_state =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -