def get_timeline_entries(record): entries = [] si = record.standard_information() fn = record.filename_information() if si and fn: filename = fn.filename() entries.extend(create_safe_timeline_entries(si, "$SI", filename)) for b in record.attributes(): if b.type() != ATTR_TYPE.FILENAME_INFORMATION: continue attr = FilenameAttribute(b.value(), 0, record) attr_filename = attr.filename() entries.extend(create_safe_timeline_entries(attr, "$FN", attr_filename)) indxroot = record.attribute(ATTR_TYPE.INDEX_ROOT) if indxroot and indxroot.non_resident() == 0: irh = IndexRootHeader(indxroot.value(), 0, False) for e in irh.node_header().entries(): fn = e.filename_information() fn_filename = fn.filename() entries.extend( create_safe_timeline_entries(fn, "INDX", fn_filename)) for e in irh.node_header().slack_entries(): fn = e.filename_information() fn_filename = fn.filename() entries.extend( create_safe_timeline_entries(fn, "slack-INDX", fn_filename)) return sorted( entries, key=lambda x: x["timestamp"] or datetime.datetime(1970, 1, 1, 0, 0, 0))
def make_model(record, path): active_data = record.active_data() slack_data = record.slack_data() model = { "magic": record.magic(), "path": path, "inode": record.inode, "is_active": record.is_active(), "is_directory": record.is_directory(), "size": 0, # updated below "standard_information": make_standard_information_model(record.standard_information()), "filename_information": make_filename_information_model(record.filename_information()), "owner_id": 0, # updated below "security_id": 0, # updated below "quota_charged": 0, # updated below "usn": 0, # updated below "filenames": [], "attributes": [], "indx_entries": [], "slack_indx_entries": [], "timeline": get_timeline_entries(record), "active_ascii_strings": ascii_strings(active_data), "active_unicode_strings": unicode_strings(active_data), "slack_ascii_strings": ascii_strings(slack_data), "slack_unicode_strings": unicode_strings(slack_data), } if not record.is_directory(): data_attr = record.data_attribute() if data_attr and data_attr.non_resident() > 0: model["size"] = data_attr.data_size() elif record.filename_information() is not None: model["size"] = record.filename_information().logical_size() else: model["size"] = 0 for b in record.attributes(): if b.type() != ATTR_TYPE.FILENAME_INFORMATION: continue attr = FilenameAttribute(b.value(), 0, record) model["filenames"].append(make_filename_information_model(attr)) for b in record.attributes(): model["attributes"].append(make_attribute_model(b)) indxroot = record.attribute(ATTR_TYPE.INDEX_ROOT) if indxroot and indxroot.non_resident() == 0: irh = IndexRootHeader(indxroot.value(), 0, False) for e in irh.node_header().entries(): m = make_filename_information_model(e.filename_information()) m["inode"] = MREF(e.mft_reference()) m["sequence_num"] = MSEQNO(e.mft_reference()) model["indx_entries"].append(m) for e in irh.node_header().slack_entries(): m = make_filename_information_model(e.filename_information()) m["inode"] = MREF(e.mft_reference()) m["sequence_num"] = MSEQNO(e.mft_reference()) model["slack_indx_entries"].append(m) return model