Beispiel #1
0
 def test_samples(self):
     if sys.version_info[0] > 2:
          # Unfortunately, olevba3 doesn't have extract_form_strings_extended
          return
     for sample, expected_result in SAMPLES:
         full_name = join(DATA_BASE_DIR, 'oleform', sample)
         parser = VBA_Parser(full_name)
         variables = list(parser.extract_form_strings_extended())
         self.assertEqual(variables, expected_result)
Beispiel #2
0
 def test_samples(self):
     if sys.version_info[0] > 2:
          # Unfortunately, olevba3 doesn't have extract_form_strings_extended
          return
     for sample, expected_result in SAMPLES:
         full_name = join(DATA_BASE_DIR, 'oleform', sample)
         parser = VBA_Parser(full_name)
         variables = list(parser.extract_form_strings_extended())
         self.assertEqual(variables, expected_result)
Beispiel #3
0
def process_file (container, filename, data,
                  altparser=False, strip_useless=False):
    """
    Process a single file

    :param container: str, path and filename of container if the file is within
    a zip archive, None otherwise.
    :param filename: str, path and filename of file on disk, or within the container.
    :param data: bytes, content of the file if it is in a container, None if it is a file on disk.
    """
    #TODO: replace print by writing to a provided output file (sys.stdout by default)
    if container:
        display_filename = '%s in %s' % (filename, container)
    else:
        display_filename = filename
    print '='*79
    print 'FILE:', display_filename
    vm = ViperMonkey()
    try:
        #TODO: handle olefile errors, when an OLE file is malformed
        vba = VBA_Parser(filename, data, relaxed=True)
        print 'Type:', vba.type
        if vba.detect_vba_macros():

            # Read in document metadata.
            try:
                ole = olefile.OleFileIO(filename)
                vba_library.meta = ole.get_metadata()
            except:
                vba_library.meta = {}

            # Parse the VBA streams.
            comp_modules = parse_streams(vba, strip_useless)
            for m in comp_modules:
                vm.add_compiled_module(m)

            # Pull out form variables.
            for (subfilename, stream_path, form_variables) in vba.extract_form_strings_extended():
                if form_variables is not None:
                    var_name = form_variables['name']
                    macro_name = stream_path
                    if ("/" in macro_name):
                        start = macro_name.rindex("/") + 1
                        macro_name = macro_name[start:]
                    global_var_name = (macro_name + "." + var_name).encode('ascii', 'ignore')
                    val = form_variables['value']
                    vm.globals[global_var_name.lower()] = val
                    log.debug("Added VBA form variable %r = %r to globals." % (global_var_name, val))
                
            print '-'*79
            print 'TRACING VBA CODE (entrypoint = Auto*):'
            vm.trace()
            # print table of all recorded actions
            print('Recorded Actions:')
            print(vm.dump_actions())

        else:
            print 'No VBA macros found.'
    except: #TypeError:
        #raise
        #TODO: print more info if debug mode
        #print sys.exc_value
        # display the exception with full stack trace for debugging, but do not stop:
        traceback.print_exc()
    print ''
Beispiel #4
0
def process_file(container,
                 filename,
                 data,
                 altparser=False,
                 strip_useless=False,
                 entry_points=None):
    """
    Process a single file

    :param container: str, path and filename of container if the file is within
    a zip archive, None otherwise.
    :param filename: str, path and filename of file on disk, or within the container.
    :param data: bytes, content of the file if it is in a container, None if it is a file on disk.

    :return A list of actions if actions found, an empty list if no actions found, and None if there
    was an error.
    """
    #TODO: replace print by writing to a provided output file (sys.stdout by default)
    if container:
        display_filename = '%s in %s' % (filename, container)
    else:
        display_filename = filename
    print '=' * 79
    print 'FILE:', display_filename
    vm = ViperMonkey()
    if (entry_points is not None):
        for entry_point in entry_points:
            vm.entry_points.append(entry_point)
    try:
        #TODO: handle olefile errors, when an OLE file is malformed
        vba = VBA_Parser(filename, data, relaxed=True)
        print 'Type:', vba.type
        if vba.detect_vba_macros():

            # Read in document metadata.
            try:
                ole = olefile.OleFileIO(filename)
                vba_library.meta = ole.get_metadata()
                vba_object.meta = vba_library.meta
            except:
                log.error("Reading in metadata failed.")
                vba_library.meta = {}

            # Set the output directory in which to put dumped files generated by
            # the macros.
            out_dir = filename + "_artifacts"
            if ("/" in out_dir):
                start = out_dir.rindex("/") + 1
                out_dir = out_dir[start:]
            out_dir = out_dir.replace(".", "").strip()
            out_dir = "./" + out_dir + "/"
            vba_library.out_dir = out_dir

            # Parse the VBA streams.
            comp_modules = parse_streams(vba, strip_useless)
            if (comp_modules is None):
                return None
            for m in comp_modules:
                if (m != "empty"):
                    vm.add_compiled_module(m)

            # Pull out form variables.
            try:
                for (subfilename, stream_path,
                     form_variables) in vba.extract_form_strings_extended():
                    if form_variables is not None:
                        var_name = form_variables['name']
                        macro_name = stream_path
                        if ("/" in macro_name):
                            start = macro_name.rindex("/") + 1
                            macro_name = macro_name[start:]
                        global_var_name = (macro_name + "." + var_name).encode(
                            'ascii', 'ignore')
                        val = form_variables['value']
                        if (val is None):
                            val = ''
                        name = global_var_name.lower()
                        vm.globals[name] = val
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name, val))
                        vm.globals[name + ".tag"] = val
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".Tag", val))
                        vm.globals[name + ".text"] = val
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".Text", val))
            except Exception as e:
                log.error("Cannot read form strings. " + str(e))

            print '-' * 79
            print 'TRACING VBA CODE (entrypoint = Auto*):'
            if (entry_points is not None):
                log.info("Starting emulation from function(s) " +
                         str(entry_points))
            vm.trace()
            # print table of all recorded actions
            print('Recorded Actions:')
            print(vm.dump_actions())
            print ''
            return vm.actions

        else:
            print 'No VBA macros found.'
            print ''
            return []
    except Exception as e:
        if ("SystemExit" not in str(e)):
            traceback.print_exc()
        return None
Beispiel #5
0
def process_file(container,
                 filename,
                 data,
                 altparser=False,
                 strip_useless=False,
                 entry_points=None,
                 time_limit=None):
    """
    Process a single file

    :param container: str, path and filename of container if the file is within
    a zip archive, None otherwise.
    :param filename: str, path and filename of file on disk, or within the container.
    :param data: bytes, content of the file if it is in a container, None if it is a file on disk.

    :return A list of actions if actions found, an empty list if no actions found, and None if there
    was an error.
    """

    # Increase Python call depth.
    sys.setrecursionlimit(13000)

    # Set the emulation time limit.
    if (time_limit is not None):
        vba_object.max_emulation_time = datetime.now() + timedelta(
            minutes=time_limit)

    #TODO: replace print by writing to a provided output file (sys.stdout by default)
    if container:
        display_filename = '%s in %s' % (filename, container)
    else:
        display_filename = filename
    print '=' * 79
    print 'FILE:', display_filename
    vm = ViperMonkey()
    if (entry_points is not None):
        for entry_point in entry_points:
            vm.entry_points.append(entry_point)
    try:
        #TODO: handle olefile errors, when an OLE file is malformed
        if (isinstance(data, Exception)):
            data = None
        vba = VBA_Parser(filename, data, relaxed=True)
        if vba.detect_vba_macros():

            # Read in document metadata.
            try:
                ole = olefile.OleFileIO(filename)
                vba_library.meta = ole.get_metadata()
                vba_object.meta = vba_library.meta
            except Exception as e:
                log.error("Reading in metadata failed. " + str(e))
                vba_library.meta = {}

            # If this is an Excel spreadsheet, read it in with xlrd.
            try:
                log.debug("Trying to load " + filename + " with xlrd...")
                vm.loaded_excel = xlrd.open_workbook(filename)
            except Exception as e:
                log.error("Reading in file as Excel failed. " + str(e))

            # Set the output directory in which to put dumped files generated by
            # the macros.
            out_dir = filename + "_artifacts"
            if ("/" in out_dir):
                start = out_dir.rindex("/") + 1
                out_dir = out_dir[start:]
            out_dir = out_dir.replace(".", "").strip()
            out_dir = "./" + out_dir + "/"
            vba_context.out_dir = out_dir

            # Parse the VBA streams.
            comp_modules = parse_streams(vba, strip_useless)
            if (comp_modules is None):
                return None
            for m in comp_modules:
                if (m != "empty"):
                    vm.add_compiled_module(m)

            # Pull out document variables.
            for (var_name, var_val) in _read_doc_vars(filename):
                vm.doc_vars[var_name.lower()] = var_val
                log.debug(
                    "Added potential VBA doc variable %r = %r to doc_vars." %
                    (var_name, var_val))

            # Pull out custom document properties.
            for (var_name, var_val) in _read_custom_doc_props(filename):
                vm.doc_vars[var_name.lower()] = var_val
                log.debug(
                    "Added potential VBA custom doc prop variable %r = %r to doc_vars."
                    % (var_name, var_val))

            # Pull out the document text.
            vm.doc_text = _read_doc_text(filename)

            try:
                # Pull out form variables.
                for (subfilename, stream_path,
                     form_variables) in vba.extract_form_strings_extended():
                    if form_variables is not None:
                        var_name = form_variables['name']
                        macro_name = stream_path
                        if ("/" in macro_name):
                            start = macro_name.rindex("/") + 1
                            macro_name = macro_name[start:]
                        global_var_name = (macro_name + "." + var_name).encode(
                            'ascii', 'ignore').replace("\x00", "")
                        tag = form_variables['tag']
                        if (tag is None):
                            tag = ''
                        tag = tag.replace('\xb1', '').replace('\x03', '')
                        caption = form_variables['caption']
                        if (caption is None):
                            caption = ''
                        caption = caption.replace('\xb1',
                                                  '').replace('\x03', '')
                        val = form_variables['value']
                        if (val is None):
                            val = caption
                        control_tip_text = form_variables['control_tip_text']
                        if (control_tip_text is None):
                            control_tip_text = ''
                        control_tip_text = control_tip_text.replace(
                            '\xb1', '').replace('\x03', '')

                        # Save full form variable names.
                        name = global_var_name.lower()
                        vm.globals[name] = val
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name, val))
                        vm.globals[name + ".tag"] = tag
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".Tag", tag))
                        vm.globals[name + ".caption"] = caption
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".Caption", caption))
                        vm.globals[name + ".controltiptext"] = control_tip_text
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".ControlTipText",
                             control_tip_text))
                        vm.globals[name + ".text"] = val
                        log.debug(
                            "Added VBA form variable %r = %r to globals." %
                            (global_var_name + ".Text", val))

                        # Save short form variable names.
                        short_name = global_var_name.lower()
                        if ("." in short_name):
                            short_name = short_name[short_name.rindex(".") +
                                                    1:]
                            vm.globals[short_name] = val
                            log.debug(
                                "Added VBA form variable %r = %r to globals." %
                                (short_name, val))
                            vm.globals[short_name + ".tag"] = tag
                            log.debug(
                                "Added VBA form variable %r = %r to globals." %
                                (short_name + ".Tag", tag))
                            vm.globals[short_name + ".caption"] = caption
                            log.debug(
                                "Added VBA form variable %r = %r to globals." %
                                (short_name + ".Caption", caption))
                            vm.globals[short_name +
                                       ".controltiptext"] = control_tip_text
                            log.debug(
                                "Added VBA form variable %r = %r to globals." %
                                (short_name + ".ControlTipText",
                                 control_tip_text))
                            vm.globals[short_name + ".text"] = val
                            log.debug(
                                "Added VBA form variable %r = %r to globals." %
                                (short_name + ".Text", val))

            except Exception as e:
                log.error("Cannot read form strings. " + str(e))
                #traceback.print_exc()
                #raise e

            print '-' * 79
            print 'TRACING VBA CODE (entrypoint = Auto*):'
            if (entry_points is not None):
                log.info("Starting emulation from function(s) " +
                         str(entry_points))
            vm.trace()
            # print table of all recorded actions
            print('Recorded Actions:')
            print(vm.dump_actions())
            print('')
            print('VBA Builtins Called: ' + str(vm.external_funcs))
            print('')
            return (vm.actions, vm.external_funcs)

        else:
            print 'No VBA macros found.'
            print ''
            return ([], [])
    except Exception as e:
        if ("SystemExit" not in str(e)):
            traceback.print_exc()
        return None