diff --git a/parseusn.py b/parseusn.py old mode 100644 new mode 100755 index d6d441f..35d5844 --- a/parseusn.py +++ b/parseusn.py @@ -117,9 +117,13 @@ def main(argv): if mftfilename: mft_to_path = parse_mft(mftfilename) - create_temp_file(infile) + if args.tempfile: + tmpname = create_temp_file(infile) + else: + tmpname = infile + + it = file(tmpname,'rb') - it = file("{}.tmp".format(infile), 'rb') if outfile is None: ot = sys.stdout else: @@ -147,9 +151,16 @@ def main(argv): read_length = 800 position_marker = 0 - go = True + oldpos = -4 + go = True + + while (go == True): + if (position_marker <= oldpos): + #We NEVER sit still, skip to next page boundary + position_marker = oldpos + (0x1000 + 4) + position_marker = position_marker & 0xfffffffffffff000 + oldpos = position_marker - while (go is True): try: # Read the record size, read the next record # sys.stderr.write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b Offset {}".format(position_marker)) @@ -157,20 +168,24 @@ def main(argv): it.seek(position_marker, os.SEEK_SET) data = it.read(read_length) if len(data) < 60: + print("End of File at %d" % position_marker); go = False continue recordsize = struct.unpack_from('I', data)[0] - if (recordsize < 0): - go = False # Invalid data can create an endless loop + if (recordsize < 0) : + continue + if (recordsize >1024) : + continue + if (recordsize < 60): # Note: There are places in the test $USNJRNL$J file where there are gaps between records that are not accounted for by the record size. # The gaps are always 0x00 filled. If the record size is zero, move forward until the next non zero byte is found. The largest gap I found was 296 bytes. gap_size = len(data.lstrip('\x00')) if gap_size < 1: - break + continue if gap_size == read_length: position_marker += 8 continue @@ -181,7 +196,7 @@ def main(argv): position_marker = position_marker + 800 - gap_size # records are aligned at 0x0 or 0x8, so zero out least significant 3 bits # this is necessary if the first non-zero byte is not found at an 0x0 or 0x8 offset - position_marker = position_marker & 0xfffffff8 + position_marker = position_marker & 0xfffffffffffffff8 continue it.seek(position_marker) @@ -193,8 +208,8 @@ def main(argv): sys.stderr.write("\nLength of data is {}\n".format(len(data))) position_marker = position_marker + recordsize # Initially forgot this. A struct error would loop forever... continue - if usn_record is None: - position_marker = position_marker + recordsize + if usn_record == None: + position_marker = position_marker + 4 continue usn_record = deflag_item(usn_record, flags) @@ -276,23 +291,21 @@ def main(argv): except struct.error, e: sys.stderr.write(e.message) - go = False sys.stderr.write("Struct format error at Tell: {}\n".format(it.tell())) except: - go = False - print ("Unexpected error:", sys.exc_info()[0]) - raise + print ("Unexpected error at %d:" % position_marker, sys.exc_info()[0]) it.close() ot.close() + if args.tempfile: # replace original sparse file USN with temp to save space since beginning of file is just NULLs - if args.replace: - os.unlink("{}".format(infile)) - os.rename("{}.tmp".format(infile), "{}".format(infile)) - else: - os.unlink("{}.tmp".format(infile)) + if args.replace: + os.unlink("{}".format(infile)) + os.rename(tmpname, "{}".format(infile)) + else: + os.unlink(tmpname) exit(0) @@ -318,6 +331,8 @@ def cliargs(): parser.add_argument('-r', '--replace', required=False, action='store_true', dest='replace', default=False, help='Replace original file with temp file (removes NULLs in sparse file).' ) + parser.add_argument('-n', '--notemp', required=False, action='store_false', dest='tempfile', default=True, + help='Do not create a tempfile without leading 0x00 bytes, this saves copy time') args = parser.parse_args() return args @@ -334,8 +349,9 @@ def create_temp_file(infile): position = it.tell() - len(data) it.seek(position) - # replace main file with working file, then clean up - ot = file("{}.tmp".format(infile), 'wb') + tmpname = "{}.tmp".format(infile) + #replace main file with working file, then clean up + ot = file(tmpname,'wb') while (True): data = it.read(655360) if len(data) < 655359: @@ -347,6 +363,7 @@ def create_temp_file(infile): it.close() ot.close() data = '' + return tmpname def parse_mft(mftfile):