def parse_mft(file):

    # The analyzeMFT library is only somewhat written to support being modular and used in another program/script.
    # As such, to access some functionality it is necessary to trick the library into believing it is being
    # called from command line. To do so, I have implemented OptionParser to pass arguguments in a way the
    # library understands. The below arguments, stored in the variable options, tell analyzeMFT to use the local
    # timezone, perform anomaly detection while processing the $MFT and that the arguments "inmemory",
    # "debug" and "useGUI" are unset and therefore False.
    input_file = open(file, 'rb')
    args = ["--localtz", "True", "--anomaly", "True"]
    parser = OptionParser()
    parser.add_option("--inmemory", dest="inmemory")
    parser.add_option("--debug", dest="debug")
    parser.add_option("--localtz", dest="localtz")
    parser.add_option("--UseGUI", dest="UseGUI")
    parser.add_option("--anomaly", dest="anomaly")
    (options, args) = parser.parse_args(args)
    date_settings = date_options()

    # Read the first 1024 bytes of the $MFT. Each record is 1024 bytes so a single record is being read.
    # Also, open a handle to the CSV we will write all of the parsed $MFT data to.
    raw_record = input_file.read(1024)
    parsed_mft = csv.writer(open(os.getcwd() + "/parsed_mft.csv", 'wb'),
                            dialect=csv.excel,
                            quoting=1)

    # If the raw MFT record is not blank, pass the raw record to analyzeMFT's parser along with the
    # necessary options set previously. If the parsed record is an actual file it will have $FILE_NAME
    # attributes. Some NTFS inodes are reserved or not used and therefore will not have a $FILE_NAME
    # record. If this is the case, do not attempt to read its name and mark it as haviing no FN record.
    #  When done, read the next 1024 bytes of the $MFT. The first iteration passes the argument 'True'
    # to the mft_to_csv function telling it to print the column headers. In doing so, we are skipping
    # reading in any attributes of $MFT since we are not concerned with an attacker timestomping it.
    # The result is a CSV containing a parse $MFT.
    if raw_record != "":

        mft_record = {}
        mft_record = mft.parse_record(raw_record, options)

        parsed_mft.writerow(mft.mft_to_csv(mft_record, True, date_settings))
        raw_record = input_file.read(1024)

    while raw_record != "":

        mft_record = {}
        mft_record = mft.parse_record(raw_record, options)

        if mft_record['fncnt'] != 0:
            mft_record['filename'] = mft_record[('fn', 0)]["name"]
        else:
            mft_record['filename'] = "NoFNRecord"

        parsed_mft.writerow(mft.mft_to_csv(mft_record, False, date_settings))
        raw_record = input_file.read(1024)
Esempio n. 2
0
    def do_output(self, record):

        if self.options.inmemory:
            self.fullmft[self.num_records] = record

        if self.options.output is not None:
            self.file_csv.writerow(mft.mft_to_csv(record, False, self.options))

        if self.options.json is not None:
            with open(self.options.json, 'a') as outfile:
                json.dump(mft.mft_to_json(record), outfile)
                outfile.write('\n')

        if self.options.csvtimefile is not None:
            self.file_csv_time.write(mft.mft_to_l2t(record))

        if self.options.bodyfile is not None:
            self.file_body.write(
                mft.mft_to_body(record, self.options.bodyfull,
                                self.options.bodystd))

        if self.options.progress:
            if self.num_records % (self.mftsize /
                                   5) == 0 and self.num_records > 0:
                print(
                    'Building MFT: {0:.0f}'.format(
                        100.0 * self.num_records / self.mftsize) + '%')
Esempio n. 3
0
    def process_mft_file(self):

        self.sizecheck()

        self.build_filepaths()

        # reset the file reading
        self.num_records = 0
        self.file_mft.seek(0)
        raw_record = self.file_mft.read(1024)

        if self.options.output is not None:
            self.file_csv.writerow(mft.mft_to_csv(None, True, self.options))

        while raw_record != "":
            record = mft.parse_record(raw_record, self.options)
            if self.options.debug:
                print(record)

            record['filename'] = self.mft[self.num_records]['filename']

            self.do_output(record)

            self.num_records += 1

            if record['ads'] > 0:
                for i in range(0, record['ads']):
                    #                         print "ADS: %s" % (record['data_name', i])
                    record_ads = record.copy()
                    record_ads['filename'] = record['filename'] + ':' + record[
                        'data_name', i]
                    self.do_output(record_ads)

            raw_record = self.file_mft.read(1024)
Esempio n. 4
0
    def process_mft_file(self):
        self.sizecheck()
        self.build_filepaths()

        # reset the file reading
        self.num_records = 0
        self.file_mft.seek(0)
        raw_record = self.file_mft.read(1024)
        if self.options.output is not None:
            header_values = mft.mft_to_csv(None, True, self.options)
            self.file_csv.writerow(header_values)

        while raw_record:
            record = mft.parse_record(raw_record, self.options)
            record['filename'] = self.mft[self.num_records]['filename']
            self.do_output(record)
            self.num_records += 1

            if record['ads'] > 0:
                for i in range(0, record['ads']):
                    record_ads = record.copy()
                    record_ads['filename'] = record['filename'] + ':' + record[
                        'data_name', i].decode("utf-8")
                    self.do_output(record_ads)

            raw_record = self.file_mft.read(1024)