def get_template(record, record_xml):
    """
    Given a complete Record, parse out the nodes that make up the Template
      and return it as a Template.

    @type record: Record
    @type record_xml: str
    @rtype: Template
    """
    template = _get_complete_template(record.root())
    return Template(int(get_eid(record_xml)), template)
Beispiel #2
0
def get_template(record, record_xml):
    """
    Given a complete Record, parse out the nodes that make up the Template
      and return it as a Template.

    @type record: Record
    @type record_xml: str
    @rtype: Template
    """
    template = _get_complete_template(record.root())
    return Template(int(get_eid(record_xml)), template)
def extract_chunk(buf, offset, state, templates):
    """
    Parse an EVTX chunk
      updating the State with new valid records, and
      extracting the templates into a TemplateDatabase.

    @sideeffect: parameter `templates`
    @sideeffect: parameter `state`

    @type buf: bytestring
    @type offset: int
    @type state: State
    @type templates: TemplateDatabase
    """
    logger.debug("Considering chunk at offset %d", offset)

    chunk = ChunkHeader(buf, offset)

    xml = []
    cache = {}
    for record in chunk.records():
        try:
            offset = record.offset()
            logger.debug("Considering record at offset %d",  offset)
            record_xml = evtx_record_xml_view(record, cache=cache)
            eid = get_eid(record_xml)

            state.add_valid_record(offset, eid, record_xml)

            template = get_template(record, record_xml)
            templates.add_template(template)
        except UnicodeEncodeError:
            logger.info("Unicode encoding issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except UnicodeDecodeError:
            logger.info("Unicode decoding issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except InvalidRecordException:
            logger.info("EVTX parsing issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except Exception as e:
            logger.info("Unknown exception processing record at %s: %s" % \
                        (hex(record.offset()), str(e)))
            continue
Beispiel #4
0
def extract_chunk(buf, offset, state, templates):
    """
    Parse an EVTX chunk
      updating the State with new valid records, and
      extracting the templates into a TemplateDatabase.

    @sideeffect: parameter `templates`
    @sideeffect: parameter `state`

    @type buf: bytestring
    @type offset: int
    @type state: State
    @type templates: TemplateDatabase
    """
    logger.debug("Considering chunk at offset %d", offset)

    chunk = ChunkHeader(buf, offset)

    xml = []
    cache = {}
    for record in chunk.records():
        try:
            offset = record.offset()
            logger.debug("Considering record at offset %d", offset)
            record_xml = evtx_record_xml_view(record, cache=cache)
            eid = get_eid(record_xml)

            state.add_valid_record(offset, eid, record_xml)

            template = get_template(record, record_xml)
            templates.add_template(template)
        except UnicodeEncodeError:
            logger.info("Unicode encoding issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except UnicodeDecodeError:
            logger.info("Unicode decoding issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except InvalidRecordException:
            logger.info("EVTX parsing issue processing record at %s" % \
                        hex(record.offset()))
            continue
        except Exception as e:
            logger.info("Unknown exception processing record at %s: %s" % \
                        (hex(record.offset()), str(e)))
            continue
#!/bin/python#    This file is part of recover-evtx.##   Copyright 2013 Willi Ballenthin <*****@*****.**>#                    while at Mandiant <http://www.mandiant.com>##   Licensed under the Apache License, Version 2.0 (the "License");#   you may not use this file except in compliance with the License.#   You may obtain a copy of the License at##       http://www.apache.org/licenses/LICENSE-2.0##   Unless required by applicable law or agreed to in writing, software#   distributed under the License is distributed on an "AS IS" BASIS,#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.#   See the License for the specific language governing permissions and#   limitations under the License.
import reimport logging
from Evtx.Evtx import ChunkHeaderfrom Evtx.Nodes import BXmlTypeNodefrom Evtx.Evtx import InvalidRecordExceptionfrom Evtx.Views import evtx_record_xml_view, evtx_template_readable_viewfrom Progress import NullProgressfrom State import Statefrom TemplateDatabase import TemplateDatabasefrom TemplateDatabase import Template
from recovery_utils import get_eid, Mmap, do_common_argparse_config
logger = logging.getLogger("extract_records")
_replacement_patterns = {i: re.compile("\[(Normal|Conditional) Substitution\(index=%d, type=\d+\)\]" % i) for i in xrange(35)}def _make_replacement(template, index, substitution): """    Makes a substitution given a template as a string.    Implementation is a huge hack that depends on the    brittle template_format() output.    @type template: str    @type index: int    @type substitution: str    @rtype: str """ if index not in _replacement_patterns:        from_pattern = re.compile("\[(Normal|Conditional) Substitution\(index=%d, type=\d+\)\]" % index)        _replacement_patterns[index] = from_pattern return _replacement_patterns[index].sub(substitution, template)

def _get_complete_template(root, current_index=0): """    Gets the template from a RootNode while resolving any    nested templates and fixing up their indices.    Depth first ordering/indexing.    Implementation is a huge hack that depends on the      brittle template_format() output.    @type root: RootNode    @type current_index: int    @rtype: str """    template = evtx_template_readable_view(root)  # TODO(wb): make sure this is working
 # walk through each substitution. # if its a normal node, continue # else its a subtemplate, and we count the number of substitutions _it_ has #   so that we can later fixup all the indices    replacements = [] for index, substitution in enumerate(root.substitutions()): # find all sub-templates if not isinstance(substitution, BXmlTypeNode):            replacements.append(current_index + index) continue # TODO(wb): hack here accessing ._root        subtemplate = _get_complete_template(substitution._root, current_index=current_index + index)        replacements.append(subtemplate)        current_index += subtemplate.count("Substitution(index=")    replacements.reverse()
 # now walk through all the indices and fix them up depth-first for i, replacement in enumerate(replacements):        index = len(replacements) - i - 1 if isinstance(replacement, int): # fixup index            from_pattern = "index=%d," % index            to_pattern = "index=%d," % replacement            template = template.replace(from_pattern, to_pattern) if isinstance(replacement, basestring): # insert sub-template            template = _make_replacement(template, index, replacement) return template

def get_template(record, record_xml): """    Given a complete Record, parse out the nodes that make up the Template      and return it as a Template.    @type record: Record    @type record_xml: str    @rtype: Template """    template = _get_complete_template(record.root()) return Template(int(get_eid(record_xml)), template)

def extract_chunk(buf, offset, state, templates): """    Parse an EVTX chunk      updating the State with new valid records, and      extracting the templates into a TemplateDatabase.    @sideeffect: parameter `templates`    @sideeffect: parameter `state`    @type buf: bytestring    @type offset: int    @type state: State    @type templates: TemplateDatabase """    logger.debug("Considering chunk at offset %d", offset)
    chunk = ChunkHeader(buf, offset)
    xml = []    cache = {} for record in chunk.records(): try:            offset = record.offset()            logger.debug("Considering record at offset %d",  offset)            record_xml = evtx_record_xml_view(record, cache=cache)            eid = get_eid(record_xml)
            state.add_valid_record(offset, eid, record_xml)
            template = get_template(record, record_xml)            templates.add_template(template) except UnicodeEncodeError:            logger.info("Unicode encoding issue processing record at %s" % \ hex(record.offset())) continue except UnicodeDecodeError:            logger.info("Unicode decoding issue processing record at %s" % \ hex(record.offset())) continue except InvalidRecordException:            logger.info("EVTX parsing issue processing record at %s" % \ hex(record.offset())) continue except Exception as e:            logger.info("Unknown exception processing record at %s: %s" % \                        (hex(record.offset()), str(e))) continue

def extract_valid_evtx_records_and_templates(state, templates, buf, progress_class=NullProgress):    progress = progress_class(len(state.get_valid_chunk_offsets()) - 1) for i, chunk_offset in enumerate(state.get_valid_chunk_offsets()):        extract_chunk(buf, chunk_offset, state, templates)        progress.set_current(i)    progress.set_complete()

def main():    args = do_common_argparse_config("Extract valid EVTX records and templates.")
 with State(args.project_json) as state: if len(state.get_valid_chunk_offsets()) == 0:            logger.warn("No valid chunk offsets recorded. Perhaps you haven't yet run find_evtx_chunks?") return with TemplateDatabase(args.templates_json) as templates: with Mmap(args.image) as buf:                num_templates_before = templates.get_number_of_templates()                num_valid_records_before = len(state.get_valid_records())                extract_valid_evtx_records_and_templates(state, templates, buf, progress_class=args.progress_class)                num_templates_after = templates.get_number_of_templates()                num_valid_records_after = len(state.get_valid_records()) print("# Found %d new templates." % (num_templates_after - num_templates_before)) print("# Found %d new valid records." % (num_valid_records_after - num_valid_records_before))
if __name__ == "__main__":    main()