示例#1
0
    def parse_vba(self, save_path):
        vba = VBA_Parser(__sessions__.current.file.path)
        # Check for Macros
        if not vba.detect_vba_macros():
            self.log('error', "No Macro's Detected")
            return
        self.log('info', "Macro's Detected")
        try:
            for (filename, stream_path, vba_filename,
                 vba_code) in vba.extract_macros():
                self.log('info', "Stream Details")
                self.log('item', "OLE Stream: {0}".format(stream_path))
                self.log('item', "VBA Filename: {0}".format(vba_filename))
                autoexec_keywords = detect_autoexec(vba_code)
                if autoexec_keywords:
                    self.log('info', "AutoRun Macros Found")
                    rows = []
                    for keyword, description in autoexec_keywords:
                        rows.append([keyword, description])
                    self.log(
                        'table',
                        dict(header=['KeyWord', 'Description'], rows=rows))
                # Match Keyword Types
                suspicious_keywords = detect_suspicious(vba_code)
                if suspicious_keywords:
                    self.log('info', "Suspicious Keywords Found")
                    rows = []
                    for keyword, description in suspicious_keywords:
                        rows.append([keyword, description])
                    self.log(
                        'table',
                        dict(header=['KeyWord', 'Description'], rows=rows))
                # Match IOCs
                patterns = detect_patterns(vba_code)
                if patterns:
                    self.log('info', "Suspicious Keywords Found")
                    rows = []
                    for pattern_type, value in patterns:
                        rows.append([pattern_type, value])
                    self.log('table',
                             dict(header=['Pattern', 'Value'], rows=rows))

                # Save the code to external File
                if save_path:
                    try:
                        with open(save_path, 'w') as out:
                            out.write(vba_code)
                        self.log('info',
                                 "Writing VBA Code to {0}".format(save_path))
                    except:
                        self.log('Error',
                                 "Unable to write to {0}".format(save_path))
                    return
        except:
            self.log('Error', "Unable to Process File")
        # Close the file
        vba.close()
示例#2
0
    def get_report(self):
        """ Return oletools report or create if not already cached. """
        if self.sample.oletools_report is not None:
            return self.sample.oletools_report

        report = {
            'autoexec': [],
            'suspicious': [],
        }

        file_path = self.sample.file_path
        try:
            vbaparser = VBA_Parser(file_path)

            # VBA_Parser reports macros for office documents
            report['has_macros'] = vbaparser.detect_vba_macros(
            ) or vbaparser.detect_xlm_macros()
            try:
                report['vba'] = vbaparser.reveal()
            except TypeError:
                # office document with no macros
                pass

            all_macros = vbaparser.extract_all_macros()
            if (report['has_macros'] and len(all_macros) == 1
                    and isinstance(all_macros[0], tuple)
                    and len(all_macros[0]) >= 3
                    and all_macros[0][2] == file_path):
                logger.warning(
                    "Buggy oletools version detected, result overridden. May "
                    "lead to false negatives, please update to fixed version")
                report['has_macros'] = False

            if vbaparser.detect_vba_macros():
                vb_code = vbaparser.extract_all_macros()
                for (_, _, _, c) in vb_code:
                    autoexec = detect_autoexec(c)
                    if len(autoexec) >= 1:
                        report['autoexec'].append(autoexec[0])

                    suspicious = detect_suspicious(c)
                    if len(suspicious) >= 1:
                        report['suspicious'].append(suspicious[0])

            vbaparser.close()
        except IOError:
            raise
        except (TypeError, FileOpenError):
            # The given file is not an office document.
            pass
        except Exception as error:
            logger.exception(error)

        report = OletoolsReport(report)
        self.sample.register_oletools_report(report)
        return report
示例#3
0
文件: office.py 项目: 4g3n7/viper
 def parse_vba(self, save_path):
     save = False
     vba = VBA_Parser(__sessions__.current.file.path)
     # Check for Macros
     if not vba.detect_vba_macros():
         self.log('error', "No Macro's Detected")
         return
     self.log('info', "Macro's Detected")
     try:
         run_rows = []
         word_rows = []
         pattern_rows = []
         for (filename, stream_path, vba_filename, vba_code) in vba.extract_macros():
             self.log('info', "Stream Details")
             self.log('item', "OLE Stream: {0}".format(string_clean(stream_path)))
             self.log('item', "VBA Filename: {0}".format(string_clean(vba_filename)))
             autoexec_keywords = detect_autoexec(vba_code)
             if autoexec_keywords:
                 for keyword, description in autoexec_keywords:
                     run_rows.append([keyword, description])
                 
             # Match Keyword Types
             suspicious_keywords = detect_suspicious(vba_code)
             if suspicious_keywords:
                 for keyword, description in suspicious_keywords:
                     word_rows.append([keyword, description])
                 
             # Match IOCs
             patterns = detect_patterns(vba_code)
             if patterns:
                 for pattern_type, value in patterns:
                     pattern_rows.append([pattern_type, value])
                 
             # Save the code to external File
             if save_path:
                 try:
                     with open(save_path, 'a') as out:
                         out.write(vba_code)
                     save = True
                 except:
                     self.log('Error', "Unable to write to {0}".format(save_path))
                     return
         # Print all Tables together
         self.log('info', "AutoRun Macros Found")
         self.log('table', dict(header=['KeyWord', 'Description'], rows=run_rows))
         self.log('info', "Suspicious Keywords Found")
         self.log('table', dict(header=['KeyWord', 'Description'], rows=word_rows))
         self.log('info', "Suspicious Patterns Found")
         self.log('table', dict(header=['Pattern', 'Value'], rows=pattern_rows))
         if save:
             self.log('success', "Writing VBA Code to {0}".format(save_path))
     except:
         self.log('Error', "Unable to Process File")
     # Close the file
     vba.close()
示例#4
0
for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
  print ("- "*79)
  print ("filename    :", filename)
  print ("OLE stream  :", stream_path)
  print ("VBA filename:", vba_filename)
  print ("- "*39)
  print ("vba_code",vba_code)

     
vba_scanner = VBA_Scanner(vba_code)
results = vba_scanner.scan(include_decoded_strings=True)
for kw_type, keyword, description in results:
 print ("type=%s - keyword=%s - description=%s" % (kw_type, keyword, description))
     
autoexec_keywords = detect_autoexec(vba_code)
if autoexec_keywords:
 print("Auto-executable Macro keyword is detected. :")
for keyword, description in autoexec_keywords:
   print("%s: %s' % (keyword, description)")
else:
 print ("Auto-executable Macro keywords is not detected.")

results = vbaparser.analyze_macros()
for kw_type, keyword, description in results:
 print ("type=%s - keyword=%s - description=%s" % (kw_type, keyword, description))
 print ("AutoExec keywords: %d" % vbaparser.nb_autoexec)
 print ("Suspicious keywords: %d" % vbaparser.nb_suspicious)
 print ("IOCs: %d" % vbaparser.nb_iocs)
 print ("Hex obfuscated strings: %d" % vbaparser.nb_hexstrings)
 print ("Base64 obfuscated strings: %d" % vbaparser.nb_base64strings)
示例#5
0
    def _parse(self, filepath: str) -> Dict[str, Any]:
        """Parses an office document for static information.
        @param filepath: Path to the file to be analyzed.
        @return: results dict or None
        """

        results = {}
        if not HAVE_OLETOOLS:
            return results

        vba = False
        if is_rtf(filepath):
            try:
                with open(filepath, "rb") as f:
                    contents = f.read()
                temp_results = self._parse_rtf(contents)
                if temp_results:
                    results["office_rtf"] = temp_results
            except Exception as e:
                log.error(e, exc_info=True)
        else:
            try:
                vba = VBA_Parser(filepath)
            except ValueError as e:
                log.error("Error VBA_Parser: %s", str(e))
            except Exception:
                return results
        try:
            # extract DDE
            dde = extract_dde(filepath)
            if dde:
                results["office_dde"] = convert_to_printable(dde)
        except (csv_error, UnicodeDecodeError):
            pass
        except AttributeError:
            log.warning(
                "OleFile library bug: AttributeError! fix: pip3 install -U olefile"
            )
        except Exception as e:
            log.error(e, exc_info=True)

        officeresults = {"Metadata": {}}
        macro_folder = os.path.join(CUCKOO_ROOT, "storage", "analyses",
                                    self.task_id, "macros")
        if olefile.isOleFile(filepath):
            with olefile.OleFileIO(filepath) as ole:
                meta = ole.get_metadata()
                # must be left this way or we won't see the results
                officeresults["Metadata"] = self._get_meta(meta)
        else:
            with contextlib.suppress(KeyError):
                officeresults["Metadata"] = self._get_xml_meta(filepath)
        if vba and vba.detect_vba_macros():
            officeresults["Metadata"]["HasMacros"] = "Yes"
            # Create IOC and category vars. We do this before processing the
            # macro(s) to avoid overwriting data when there are multiple
            # macros in a single file.
            officeresults["Macro"] = {"Code": {}, "info": {}, "Analysis": {}}
            ctr = 0

            try:
                for _, _, vba_filename, vba_code in vba.extract_macros():
                    vba_code = filter_vba(vba_code)
                    if vba_code.strip() != "":
                        # Handle all macros
                        ctr += 1
                        outputname = f"Macro{ctr}"
                        officeresults["Macro"]["Code"][outputname] = [
                            (convert_to_printable(vba_filename),
                             convert_to_printable(vba_code))
                        ]
                        if not os.path.exists(macro_folder):
                            os.makedirs(macro_folder)
                        macro_file = os.path.join(macro_folder, outputname)
                        with open(macro_file, "w") as f:
                            f.write(convert_to_printable(vba_code))
                        officeresults["Macro"]["info"][outputname] = {
                            "yara_macro":
                            File(macro_file).get_yara(category="macro")
                        }
                        officeresults["Macro"]["info"][outputname][
                            "yara_macro"].extend(
                                File(macro_file).get_yara(category="CAPE"))

                        try:
                            iocs = vbadeobf.parse_macro(vba_code)
                            for pattern, match in iocs:
                                officeresults["Macro"]["Analysis"].setdefault(
                                    "IOCs", []).append((pattern, match))
                        except ValueError as e:
                            log.error("Can't parse macros for %s - %s ",
                                      filepath, str(e))
                        except Exception as e:
                            log.error(e, exc_info=True)
                        for keyword, description in detect_autoexec(vba_code):
                            officeresults["Macro"]["Analysis"].setdefault(
                                "AutoExec", []).append(
                                    (keyword.replace(".", "_"), description))
                        for keyword, description in detect_suspicious(
                                vba_code):
                            officeresults["Macro"]["Analysis"].setdefault(
                                "Suspicious", []).append(
                                    (keyword.replace(".", "_"), description))
                        for encoded, decoded in detect_hex_strings(vba_code):
                            officeresults["Macro"]["Analysis"].setdefault(
                                "HexStrings", []).append(
                                    (encoded, convert_to_printable(decoded)))
            except (AssertionError, UnexpectedDataError) as e:
                log.warning("Macros in static.py", e)

            if HAVE_VBA2GRAPH:
                vba2graph_func(filepath, self.task_id, self.sha256)

        else:
            officeresults["Metadata"]["HasMacros"] = "No"

        try:
            for indicator in OleID(filepath).check():
                if indicator.value and indicator.name in {
                        "Word Document", "Excel Workbook",
                        "PowerPoint Presentation"
                }:
                    officeresults["Metadata"]["DocumentType"] = indicator.name
        except Exception as e:
            log.error(e, exc_info=True)

        if HAVE_XLM_DEOBF:
            tmp_xlmmacro = xlmdeobfuscate(filepath, self.task_id,
                                          self.options.get("password", ""))
            if tmp_xlmmacro:
                officeresults["XLMMacroDeobfuscator"] = tmp_xlmmacro

        return officeresults
示例#6
0
    def get_report(self):
        """ Return oletools report or create if not already cached. """
        if self.sample.oletools_report is not None:
            return self.sample.oletools_report

        report = {
            'autoexec': [],
            'suspicious' : [],
        }

        filename = self.sample.filename
        try:
            vbaparser = VBA_Parser(filename, data=self.sample.content)

            # VBA_Parser reports macros for office documents
            report['has_macros'] = vbaparser.detect_vba_macros() or vbaparser.detect_xlm_macros()
            try:
                report['vba'] = vbaparser.reveal()
            except TypeError:
                # office document with no macros
                pass

            # When called on an empty or text document oletools will falsely
            # report that it contains macros and returns a one item list of
            # macros which contains only the filename again.
            #
            # Oletool assume the submitted file is the plain text macro if
            # it can not determine another file type.
            #
            # Add a workaround to detect this behaviour and override the
            # result.
            all_macros = vbaparser.extract_all_macros()
            if (report['has_macros'] and len(all_macros) == 1
                    and isinstance(all_macros[0], tuple)
                    and len(all_macros[0]) >= 3
                    and all_macros[0][2] == filename):
                report['has_macros'] = False

            if vbaparser.detect_vba_macros():
                vb_code = vbaparser.extract_all_macros()
                for (_, _, _, c) in vb_code:
                    autoexec = detect_autoexec(c)
                    if len(autoexec) >= 1:
                        report['autoexec'].extend(autoexec)

                    suspicious = detect_suspicious(c)
                    if len(suspicious) >= 1:
                        report['suspicious'].extend(suspicious)

            vbaparser.close()
        except IOError:
            raise
        except (TypeError, FileOpenError):
            # The given file is not an office document.
            pass
        except Exception as error:
            logger.exception(error)

        report = OletoolsReport(report)
        self.sample.register_oletools_report(report)
        return report