def _load_templates(self): """ @return None """ if self._templates is None: self._templates = {} for i in xrange(32): ofs = self.unpack_dword(0x180 + (i * 4)) while ofs > 0: # unclear why these are found before the offset # this is a direct port from A.S.'s code token = self.unpack_byte(ofs - 10) pointer = self.unpack_dword(ofs - 4) if token != 0x0c or pointer != ofs: warning("Unexpected token encountered") ofs = 0 continue template = self.add_template(ofs) ofs = template.next_offset()
def _load_templates(self): """ @return None """ if self._templates is None: self._templates = {} for i in xrange(32): ofs = self.unpack_dword(0x180 + (i * 4)) while ofs > 0: # unclear why these are found before the offset # this is a direct port from A.S.'s code token = self.unpack_byte(ofs - 10) pointer = self.unpack_dword(ofs - 4) if token != 0x0C or pointer != ofs: warning("Unexpected token encountered") ofs = 0 continue template = self.add_template(ofs) ofs = template.next_offset()
def fixup(self, num_fixups, fixup_value_offset): fixup_value = self.unpack_word(fixup_value_offset) for i in range(0, num_fixups - 1): fixup_offset = 512 * (i + 1) - 2 check_value = self.unpack_word(fixup_offset) if check_value != fixup_value: warning("Bad fixup at %s" % \ (hex(self.offset() + fixup_offset))) continue new_value = self.unpack_word(fixup_value_offset + 2 + 2 * i) self.pack_word(fixup_offset, new_value) check_value = self.unpack_word(fixup_offset) debug("Fixup verified at %s and patched from %s to %s." % \ (hex(self.offset() + fixup_offset), hex(fixup_value), hex(check_value)))
def main(): parser = argparse.ArgumentParser(description='Parse NTFS ' 'filesystem structures.') parser.add_argument('-t', action="store", metavar="type", nargs=1, dest="filetype", choices=["image", "MFT", "INDX", "auto"], default="auto", help="The type of data provided.") parser.add_argument('-c', action="store", metavar="size", nargs=1, type=int, dest="clustersize", help="Use this cluster size in bytes " "(default 4096 bytes)") parser.add_argument('-o', action="store", metavar="offset", nargs=1, type=int, dest="offset", help="Offset in bytes to volume in image " "(default 32256 bytes)") parser.add_argument('-l', action="store_true", dest="indxlist", help="List file entries in INDX records") parser.add_argument('-s', action="store_true", dest="slack", help="List file entries in INDX slack space") parser.add_argument('-m', action="store_true", dest="mftlist", help="List file entries for active MFT records") parser.add_argument('-d', action="store_true", dest="deleted", help="List file entries for MFT records " "marked as deleted") parser.add_argument('-i', action="store", metavar="path|inode", nargs=1, dest="infomode", help="Print information about a path's INDX records") parser.add_argument('-e', action="store", metavar="i30", nargs=1, dest="extract", help="Used with -i, extract INDX_ALLOCATION " "attribute to a file") parser.add_argument('-f', action="store", metavar="regex", nargs=1, dest="filter", help="Only consider entries whose path " "matches this regular expression") parser.add_argument('-p', action="store", metavar="prefix", nargs=1, dest="prefix", help="Prefix paths with `prefix` rather than \\.\\") parser.add_argument('--progress', action="store_true", dest="progress", help="Update a status indicator on STDERR " "if STDOUT is redirected") parser.add_argument('-v', action="store_true", dest="verbose", help="Print debugging information") parser.add_argument('filename', action="store", help="Input INDX file path") results = parser.parse_args() global verbose verbose = results.verbose if results.filetype and results.filetype != "auto": results.filetype = results.filetype[0].lower() info("Asked to process a file with type: " + results.filetype) else: with open(results.filename, "rb") as f: b = f.read(1024) if b[0:4] == "FILE": results.filetype = "mft" elif b[0:4] == "INDX": results.filetype = "indx" else: results.filetype = "image" info("Auto-detected input file type: " + results.filetype) if results.clustersize: results.clustersize = results.clustersize[0] info("Using explicit file system cluster size %s (%s) bytes" % (str(results.clustersize), hex(results.clustersize))) else: results.clustersize = 4096 info("Assuming file system cluster size %s (%s) bytes" % (str(results.clustersize), hex(results.clustersize))) if results.offset: results.offset = results.offset[0] info("Using explicit volume offset %s (%s) bytes" % (str(results.offset), hex(results.offset))) else: results.offset = 32256 info("Assuming volume offset %s (%s) bytes" % (str(results.offset), hex(results.offset))) if results.prefix: results.prefix = results.prefix[0] info("Using path prefix " + results.prefix) if results.indxlist: info("Asked to list entries in INDX records") if results.filetype == "mft": info(" Note, only resident INDX records can be processed " "with an MFT input file") info(" If you find an interesting record, " "use -i to identify the relevant INDX record clusters") elif results.filetype == "indx": info(" Note, only records in this INDX record will be listed") elif results.filetype == "image": pass else: pass if results.slack: info("Asked to list slack entries in INDX records") info(" Note, this uses a scanning heuristic to identify records. " "These records may be corrupt or out-of-date.") if results.mftlist: info("Asked to list active file entries in the MFT") if results.filetype == "indx": error("Cannot list MFT entries of an INDX record") if results.deleted: info("Asked to list deleted file entries in the MFT") if results.filetype == "indx": error("Cannot list MFT entries of an INDX record") if results.infomode: results.infomode = results.infomode[0] info("Asked to list information about path " + results.infomode) if results.indxlist or \ results.slack or \ results.mftlist or \ results.deleted: error("Information mode (-i) cannot be run " "with file entry list modes (-l/-s/-m/-d)") if results.extract: results.extract = results.extract[0] info("Asked to extract INDX_ALLOCATION attribute " "for the path " + results.infomode) if results.extract and not results.infomode: warning("Extract (-e) doesn't make sense " "without information mode (-i)") if results.extract and not results.filetype == "image": error("Cannot extract non-resident attributes " "from anything but an image") if not (results.indxlist or results.slack or results.mftlist or results.deleted or results.infomode): error("You must choose a mode (-i/-l/-s/-m/-d)") if results.filter: results.filter = results.filter[0] info("Asked to only list file entry information " "for paths matching the regular expression: " + results.filter) if results.infomode: warning("This filter has no meaning with information mode (-i)") if results.infomode: print_indx_info(results) elif results.indxlist or \ results.slack or \ results.mftlist or \ results.deleted: print_bodyfile(results)
def try_write(s): try: sys.stdout.write(s) except (UnicodeEncodeError, UnicodeDecodeError): warning("Failed to write string " "due to encoding issue: " + str(list(s)))