コード例 #1
0
ファイル: main.py プロジェクト: m-m-adams/macroscanner
def olevba_trig(file):
    try:
        vbaparser = VBA_Parser(file)
        if vbaparser.detect_vba_macros():
            for (filename, stream_path, vba_filename,
                 vba_code) in vbaparser.extract_macros():
                print('Filename    :', filename)
                print('OLE stream  :', stream_path)
                print('VBA filename:', vba_filename)
                print('- ' * 39)
                print(vba_code)
                print('- ' * 39)

                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)
                print('Dridex obfuscated strings: %d' %
                      vbaparser.nb_dridexstrings)
                print('VBA obfuscated strings: %d' % vbaparser.nb_vbastrings)
                print("\n")

    except:
        e = sys.exc_info()[0]
        print(f'{e} from {file}')
コード例 #2
0
def EXTRACT_VBA_MACRO(s, buff):

    EXTRACT_MACRO = {}
    counter = 0

    ### TODO: REMOVE THIS WORKAROUND ONCE MODULE AUTHOR FIXES CODE ###
    ### Reference: http://stackoverflow.com/questions/32261679/strange-issue-using-logging-module-in-python/32264445#32264445
    ### Reference: https://bitbucket.org/decalage/oletools/issues/26/use-of-logger
    ### /dev/null used instead of NullHandler for 2.6 compatibility
    logging.getLogger('workaround').root.addHandler(
        logging.FileHandler('/dev/null'))
    ###

    vba = VBA_Parser('None', data=buff)

    if not vba.detect_vba_macros():
        return EXTRACT_MACRO

    for (filename, stream_path, vba_filename,
         vba_code) in vba.extract_macros():

        CHILD_MACRO = OrderedDict([('OLE Stream', stream_path),
                                   ('VBA Filename',
                                    vba_filename.decode('ascii', 'ignore')),
                                   ('Scan', scan_macro(vba_code)),
                                   ('Buffer', vba_code)])

        EXTRACT_MACRO['Object_%s' % counter] = CHILD_MACRO
        counter += 1

    return EXTRACT_MACRO
コード例 #3
0
 def parse_vba(self, save_path):
     save = False
     vbaparser = VBA_Parser(__sessions__.current.file.path)
     # Check for Macros
     if not vbaparser.detect_vba_macros():
         self.log('error', "No Macro's Detected")
         return
     self.log('info', "Macro's Detected")
     #try:
     if True:
         an_results = {'AutoExec':[], 'Suspicious':[], 'IOC':[], 'Hex String':[], 'Base64 String':[], 'Dridex String':[], 'VBA string':[]}
         for (filename, stream_path, vba_filename, vba_code) in vbaparser.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)))
             # Analyse the VBA Code
             vba_scanner = VBA_Scanner(vba_code)
             analysis = vba_scanner.scan(include_decoded_strings=True)
             for kw_type, keyword, description in analysis:
                 an_results[kw_type].append([string_clean_hex(keyword), description])
                 
             # 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=['Method', 'Description'], rows=an_results['AutoExec']))
         
         self.log('info', "Suspicious Keywords Found")
         self.log('table', dict(header=['KeyWord', 'Description'], rows=an_results['Suspicious']))
         
         self.log('info', "Possible IOC's")
         self.log('table', dict(header=['IOC', 'Type'], rows=an_results['IOC']))
         
         self.log('info', "Hex Strings")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Hex String']))
         
         self.log('info', "Base64 Strings")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Base64 String']))
         
         self.log('info', "Dridex String")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Dridex String']))
         
         self.log('info', "VBA string")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['VBA string']))
         
         
         
         if save:
             self.log('success', "Writing VBA Code to {0}".format(save_path))
     #except:
         #self.log('error', "Unable to Process File")
     # Close the file
     vbaparser.close()
コード例 #4
0
def EXTRACT_VBA_MACRO(s, buff):

   EXTRACT_MACRO = {}
   counter = 0

   ### TODO: REMOVE THIS WORKAROUND ONCE MODULE AUTHOR FIXES CODE ###
   ### Reference: http://stackoverflow.com/questions/32261679/strange-issue-using-logging-module-in-python/32264445#32264445
   ### Reference: https://bitbucket.org/decalage/oletools/issues/26/use-of-logger
   ### /dev/null used instead of NullHandler for 2.6 compatibility 
   logging.getLogger('workaround').root.addHandler(logging.FileHandler('/dev/null'))
   ###

   vba = VBA_Parser('None', data=buff)

   if not vba.detect_vba_macros():
      return EXTRACT_MACRO

   for (filename, stream_path, vba_filename, vba_code) in vba.extract_macros():

      CHILD_MACRO = OrderedDict([('OLE Stream', stream_path),
                                 ('VBA Filename', vba_filename.decode('ascii', 'ignore')),
                                 ('Scan', scan_macro(vba_code)),
                                 ('Buffer', vba_code)])

      EXTRACT_MACRO['Object_%s' % counter] = CHILD_MACRO
      counter += 1

   return EXTRACT_MACRO
コード例 #5
0
def vba2graph_from_vba_object(filepath):
    """ vba2graph as library
    Args:
        filepath (string): path to file
    """
    logger.info("Extracting macros from file")
    if HAVE_OLETOOLS:
        try:
            vba = VBA_Parser(filepath)
        except Exception as e:
            return False
    full_vba_code = ""
    for (subfilename, stream_path, vba_filename,
         vba_code) in vba.extract_macros():
        full_vba_code += 'VBA MACRO %s \n' % vba_filename
        full_vba_code += '- ' * 39 + '\n'
        # Temporary workaround. Change when oletools 0.56 will be released.
        if isinstance(vba_code, bytes):
            vba_code = vba_code.decode('utf8', errors='replace')
        full_vba_code += vba_code
    vba.close()
    if full_vba_code:
        input_vba_content = handle_olevba_input(full_vba_code)
        return input_vba_content
    return False
コード例 #6
0
ファイル: office.py プロジェクト: asymptotic/viper
 def parse_vba(self, save_path):
     save = False
     vbaparser = VBA_Parser(__sessions__.current.file.path)
     # Check for Macros
     if not vbaparser.detect_vba_macros():
         self.log('error', "No Macro's Detected")
         return
     self.log('info', "Macro's Detected")
     #try:
     if True:
         an_results = {'AutoExec':[], 'Suspicious':[], 'IOC':[], 'Hex String':[], 'Base64 String':[], 'Dridex String':[], 'VBA string':[]}
         for (filename, stream_path, vba_filename, vba_code) in vbaparser.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)))
             # Analyse the VBA Code
             vba_scanner = VBA_Scanner(vba_code)
             analysis = vba_scanner.scan(include_decoded_strings=True)
             for kw_type, keyword, description in analysis:
                 an_results[kw_type].append([string_clean_hex(keyword), description])
                 
             # 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=['Method', 'Description'], rows=an_results['AutoExec']))
         
         self.log('info', "Suspicious Keywords Found")
         self.log('table', dict(header=['KeyWord', 'Description'], rows=an_results['Suspicious']))
         
         self.log('info', "Possible IOC's")
         self.log('table', dict(header=['IOC', 'Type'], rows=an_results['IOC']))
         
         self.log('info', "Hex Strings")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Hex String']))
         
         self.log('info', "Base64 Strings")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Base64 String']))
         
         self.log('info', "Dridex String")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['Dridex String']))
         
         self.log('info', "VBA string")
         self.log('table', dict(header=['Decoded', 'Raw'], rows=an_results['VBA string']))
         
         
         
         if save:
             self.log('success', "Writing VBA Code to {0}".format(save_path))
     #except:
         #self.log('error', "Unable to Process File")
     # Close the file
     vbaparser.close()
コード例 #7
0
def process_file_scanexpr (container, filename, data):
    """
    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
    all_code = ''
    try:
        #TODO: handle olefile errors, when an OLE file is malformed
        vba = VBA_Parser(filename, data)
        print 'Type:', vba.type
        if vba.detect_vba_macros():
            #print 'Contains VBA Macros:'
            for (subfilename, stream_path, vba_filename, vba_code) in vba.extract_macros():
                # hide attribute lines:
                #TODO: option to disable attribute filtering
                vba_code_filtered = filter_vba(vba_code)
                print '-'*79
                print 'VBA MACRO %s ' % vba_filename
                print 'in file: %s - OLE stream: %s' % (subfilename, repr(stream_path))
                print '- '*39
                # detect empty macros:
                if vba_code_filtered.strip() == '':
                    print '(empty macro)'
                else:
                    # TODO: option to display code
                    print vba_code_filtered
                    vba_code = vba_collapse_long_lines(vba_code)
                    all_code += '\n' + vba_code
            print '-'*79
            print 'EVALUATED VBA EXPRESSIONS:'
            t = prettytable.PrettyTable(('Obfuscated expression', 'Evaluated value'))
            t.align = 'l'
            t.max_width['Obfuscated expression'] = 36
            t.max_width['Evaluated value'] = 36
            for expression, expr_eval in scan_expressions(all_code):
                t.add_row((repr(expression), repr(expr_eval)))
            print t


        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 ''
コード例 #8
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()
コード例 #9
0
    def getVBA(self, myfile, source='filepath'):
        '''
        Given a file, parses out the stream paths, vba code, and vba filenames for each.
        :param myfile: filename
        :param source: type of data being passed in.  Either "filepath" to indicate we need to read from disk or
        "filecontents" meaning that the file contents are being passed as a parameter.
        :return: pandas Series that can be used in concert with the pandas DataFrame apply method
        '''
        if source == 'filepath':
            filedata = open(myfile, 'rb').read()
        else:
            filedata = myfile

        entry = {}
        try:
            vbaparser = VBA_Parser('mmbot', data=filedata)
            allcode = ''
            pathnames = ''
            filenames = ''
            if vbaparser.detect_vba_macros():
                filenameslist = []
                pathnameslist = []
                vbacodelist = []
                for (filename, stream_path, filename_vba,
                     extracted_vba) in vbaparser.extract_macros():
                    vbacodelist.append(extracted_vba.decode("ascii", "ignore"))
                    #vbacodelist.append(extracted_vba.decode('utf8', 'ignore'))

                    if pathnames is None:
                        pathnameslist.append(
                            stream_path.decode("ascii", "ignore"))
                        filenameslist.append(
                            filename_vba.decode("ascii", "ignore"))
                    else:
                        pathnameslist.append(
                            stream_path.decode("ascii", "ignore"))
                        filenameslist.append(
                            filename_vba.decode("ascii", "ignore"))
                allcode = "\n\n\n\n".join(vbacodelist)
                filenames = ", ".join(filenameslist)
                pathnames = ", ".join(pathnameslist)

            else:
                pathnames = 'No VBA Macros found'
                filenames = 'No VBA Macros found'
                allcode = 'No VBA Macros found'

        except Exception as e:
            pathnames = 'Error:' + str(e)
            filenames = 'Error:' + str(e)
            allcode = 'Error:' + str(e)

        return pd.Series({
            'extracted_vba': allcode,
            'stream_path': pathnames,
            'filename_vba': filenames
        })
コード例 #10
0
ファイル: run_oletools.py プロジェクト: stoerchl/malquarium
def get_macros():
    extracted_macros = []
    macro_analysis = []
    tags = []

    try:
        vbaparser = VBA_Parser('/sample')
        vbaparser.detect_vba_macros()

        for (filename, stream_path, vba_filename,
             vba_code) in vbaparser.extract_macros():
            extracted_macros.append({
                "stream_path": stream_path,
                "vba_filename": vba_filename,
                "vba_code": vba_code
            })

        try:
            for kw_type, keyword, description in vbaparser.analyze_macros():
                macro_analysis.append({
                    "kw_type": kw_type,
                    "keyword": keyword,
                    "description": description
                })

                if keyword == 'Shell':
                    tags.append('run-file')
        except TypeError:
            pass

        macro_suspicious_categories = {
            "nb_macros": vbaparser.nb_macros,
            "nb_autoexec": vbaparser.nb_autoexec,
            "nb_suspicious": vbaparser.nb_suspicious,
            "nb_iocs": vbaparser.nb_iocs,
            "nb_hexstrings": vbaparser.nb_hexstrings,
            "nb_base64strings": vbaparser.nb_base64strings,
            "nb_dridexstrings": vbaparser.nb_dridexstrings,
            "nb_vbastrings": vbaparser.nb_vbastrings,
        }

        if vbaparser.nb_macros:
            tags.append('macros')

        if vbaparser.nb_hexstrings or vbaparser.nb_base64strings:
            tags.append('obfuscated')

    except FileOpenError:
        return None, tags

    return {
        "extracted_macros": extracted_macros,
        "macro_analysis": macro_analysis,
        "macro_suspicious_categories": macro_suspicious_categories
    }, tags
コード例 #11
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()
コード例 #12
0
def vbaparsing(filename):
    vbafile = VBA_Parser(filename)
    results = ""
    for (filename, stream_path, vba_filename,
         vba_code) in vbafile.extract_macros():
        results = results + vba_code
    result = vbafile.analyze_macros()
    for kw_type, keyword, description in result:
        results = results + 'type=%s - keyword=%s - description=%s' % (
            kw_type, keyword, description)
    return results
コード例 #13
0
def vba2graph_from_vba_object(filepath):
    logging.info("Extracting macros from file")
    full_vba_code = ""
    vba_parser = VBA_Parser(filepath)
    for (subfilename, stream_path, vba_filename, vba_code) in vba_parser.extract_macros():
        # workaround till oletools version 0.56
        if isinstance(vba_code, bytes):
            vba_code = vba_code.decode('latin1', errors='replace')
        full_vba_code += vba_code
    vba_parser.close()
    return full_vba_code
コード例 #14
0
def extract_src_codes(file):
    dic = {}
    parser = VBA_Parser(file)
    for (_, sname, _, code) in parser.extract_macros():
        sname = sname.split("/")[-1]
        if sname not in dic:
            lines = code.split("\n")[1: ]
            dic[sname] = "\n".join(lines) # remove the first line
        else:
            printError(f"Error in src_codes: repeat {sname}")
    return dic
コード例 #15
0
def parse(file_path):
    vba_folder = 'src'
    vba_parser = VBA_Parser(file_path)
    for _, _, vba_filename, vba_code in vba_parser.extract_macros():
        if not os.path.isdir(vba_folder):
            os.makedirs(vba_folder)
        with open(os.path.join(vba_folder, vba_filename),
                  'w',
                  encoding='utf-8',
                  newline='\n') as file:
            file.write(vba_code)
    vba_parser.close()
コード例 #16
0
ファイル: extractmacro.py プロジェクト: slaughterjames/static
def POE(logdir, targetfile, logging, debug):

    if (logging == True): 
        LOG = logger()             
    newlogentry = ''
    macro_dump_data = ''

    FI = fileio()

    try:        
        filedata = open(targetfile.filename, 'rb').read()
        vbaparser = VBA_Parser(targetfile.filename, data=filedata)
        if vbaparser.detect_vba_macros():
            print '[*] VBA macros found - Extracting...\n'
            if (logging == True):
                newlogentry = 'VBA macros found - Extracting...'
                LOG.WriteLog(logdir, targetfile.filename, newlogentry)
            for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
                macro_dump_data += '-' * 79 + '\n'
                try:
                    macro_dump_data += 'Filename    :' + filename.encode("ascii", "replace") + '\n'
                    macro_dump_data += 'OLE stream  :' + stream_path.encode("ascii", "replace") + '\n'                
                    macro_dump_data += 'VBA filename:' + vba_filename.encode("ascii", "replace") + '\n'
                except Exception, e:
                    print '[x] Current macro - unable to print Filename, OLE stream or VBA filename due to encoding issue (Unicode?): ', e
                macro_dump_data += '-' * 79 + '\n'
                macro_dump_data += vba_code
                FI.WriteLogFile(logdir + vba_filename, macro_dump_data)

                try:                     
                    print '[*] Macro ' + vba_filename.encode("ascii", "replace") + ' extracted to: ' + logdir + vba_filename.encode("ascii", "replace")
                    targetfile.macros.append(logdir + vba_filename.encode("ascii", "replace"))

                    if (logging == True):
                        newlogentry = 'Macro ' + vba_filename.encode("ascii", "replace") + ' extracted to: <a href=\"' + logdir + vba_filename.encode("ascii", "replace") + '\">' + vba_filename.encode("ascii", "replace") + '</a>'
                    LOG.WriteLog(logdir, targetfile.filename, newlogentry)
                    if (debug == True):
                        print '-'*79
                        print 'Filename    :', filename.encode("ascii", "replace")
                        print 'OLE stream  :', stream_path.encode("ascii", "replace")
                        print 'VBA filename:', vba_filename.encode("utf-8", "ignore")
                        print '-'*79
                except Exception, e:
                    print '[x] Current macro - unable print Filename, OLE stream or VBA filename due to encoding issue: (Unicode?)', e

                if (debug == True):
                    print vba_code

                macro_dump_data = ''
            print 'Macro List'
            for mlist in targetfile.macros:
                print mlist
コード例 #17
0
def writeVBA(workbookName):
    vbaparser = VBA_Parser('./'+workbookName)

    VBA_path = './src/VBA'
    if os.path.exists(VBA_path):
        shutil.rmtree(VBA_path)
    os.mkdir(VBA_path)

    for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
        f = open('./src/VBA/' + vba_filename, "w")
        f.write(vba_code)
        f.close()

    vbaparser.close()
コード例 #18
0
def get_vba_source_from_excel(filename):
    vbaparser = VBA_Parser(filename)

    if vbaparser.detect_vba_macros():
        print('VBA Macros found')
    else:
        print('No VBA Macros found')

    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)
コード例 #19
0
def _ole_analysis(full_targ_path):
    # This function calls a number of tools / scripts to run against document samples containing OLE data and extracts data and/or performs analysis as needed.
    try:
        vba_parse_Obj = VBA_Parser(full_targ_path)
    except AttributeError:
        return ("ERROR_PARSING", "ERROR_PARSING", "ERROR_PARSING",
                "ERROR_PARSING")
    macro_analysis_over = []
    macro_analysis_info = []
    if vba_parse_Obj.detect_vba_macros():
        vba_macro = "Present"
        # Utilizing oletools to perform analysis.

        # Grabbing info from each macro.
        MA_CNT = 1
        for (file_name, ole_stream, vba_filename,
             vba_code) in vba_parse_Obj.extract_macros():
            macro_analysis_over.append(str(MA_CNT) + ':' + str(full_targ_path))
            macro_analysis_over.append(
                str(MA_CNT) + ":Filename      :" + file_name)
            macro_analysis_over.append(
                str(MA_CNT) + ":OLE Stream    :" + ole_stream)
            macro_analysis_over.append(
                str(MA_CNT) + ":VBA Filename  :" + vba_filename)
            macro_analysis_over.append(str(MA_CNT) + ':' + vba_code)
            MA_CNT += 1

        # Grabbing some overall VBA analysis info.
        macro_flag_types = []
        macro_analysis_res = vba_parse_Obj.analyze_macros()
        if isinstance(macro_analysis_res, list):
            for iocType in macro_analysis_res:
                if str(iocType) not in macro_flag_types:
                    macro_flag_types.append(str(iocType[0]))

        if len(macro_flag_types) > 0:
            iocs = ':'.join(list(set(macro_flag_types)))
        else:
            iocs = "None"

    else:
        vba_macro = "None"
        iocs = "None"
        macro_analysis_res = "None"

    vba_parse_Obj.close()

    return (vba_macro, macro_analysis_over, str(macro_analysis_res), iocs)
コード例 #20
0
ファイル: auto_mal.py プロジェクト: 0xhughes/auto_mal
def _ole_analysis(full_targ_path):
    # This function calls a number of tools / scripts to run against document samples containing OLE data and extracts data and/or performs analysis as needed.
    try:
        vba_parse_Obj = VBA_Parser(full_targ_path)
    except AttributeError:
        return("ERROR_PARSING", "ERROR_PARSING", "ERROR_PARSING", "ERROR_PARSING")
    macro_analysis_over = []
    macro_analysis_info = []
    if vba_parse_Obj.detect_vba_macros():
        vba_macro = "Present"
        # Utilizing oletools to perform analysis.

        # Grabbing info from each macro.
        MA_CNT = 1
        for (file_name, ole_stream, vba_filename, vba_code) in vba_parse_Obj.extract_macros():
            macro_analysis_over.append(str(MA_CNT)+':'+str(full_targ_path))
            macro_analysis_over.append(str(MA_CNT)+":Filename      :"+file_name)
            macro_analysis_over.append(str(MA_CNT)+":OLE Stream    :"+ole_stream)
            macro_analysis_over.append(str(MA_CNT)+":VBA Filename  :"+vba_filename)
            macro_analysis_over.append(str(MA_CNT)+':'+vba_code)
            MA_CNT+=1

        # Grabbing some overall VBA analysis info.
        macro_flag_types = []
        macro_analysis_res = vba_parse_Obj.analyze_macros()
        if isinstance(macro_analysis_res, list):
            for iocType in macro_analysis_res:
                if str(iocType) not in macro_flag_types:
                    macro_flag_types.append(str(iocType[0]))


        if len(macro_flag_types) > 0:
            iocs = ':'.join(list(set(macro_flag_types)))
        else:
            iocs = "None"

    else:
        vba_macro = "None"
        iocs = "None"
        macro_analysis_res = "None"

    vba_parse_Obj.close()

    return(vba_macro, macro_analysis_over, str(macro_analysis_res), iocs)
コード例 #21
0
def vba2graph_from_vba_object(filepath):
    """ vba2graph as library
    Args:
        filepath (string): path to file
    """
    if HAVE_OLETOOLS:
        try:
            vba = VBA_Parser(filepath)
        except Exception as e:
            return False
    full_vba_code = ""
    for (subfilename, stream_path, vba_filename, vba_code) in vba.extract_macros():
        full_vba_code += 'VBA MACRO %s \n' % vba_filename
        full_vba_code += '- '*39 + '\n'
        full_vba_code += vba_code
    vba.close()
    if full_vba_code:
        input_vba_content = handle_olevba_input(full_vba_code)
        return input_vba_content

    return False
コード例 #22
0
ファイル: macros.py プロジェクト: unic0rn-team/safe-mail
 def detect(self, filename):
     return_list = []
     vbaparser = VBA_Parser(filename)
     if vbaparser.detect_vba_macros():
         for (filename, stream_path, vba_filename,
              vba_code) in vbaparser.extract_macros():
             return_list.append({
                 'filename': filename,
                 'ole_stream': stream_path,
                 'vba_filename': vba_filename,
                 'vba_code': vba_code
             })
         results = vbaparser.analyze_macros()
         for kw_type, keyword, description in results:
             return_list.append({
                 'type': kw_type,
                 'keyword': keyword,
                 'description': description
             })
         return_list.append({'revealed_macro': vbaparser.reveal()})
         return return_list
     else:
         return None
コード例 #23
0
    def get_vba_code(self):
        """Code analysis for malicious parts. Returns malicious code, if any."""
        if not self.has_macros:
            return "Документ не содержит макросов!"

        vbaparser = VBA_Parser(self.file_path)
        vbaparser.detect_vba_macros()
        code_list = list()

        for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
            code_list.append(vba_code)
            code = vba_code

        report_vba = code_list[0]
        macros_infos = self.macros_infos
        for i in range(len(macros_infos)):
            if macros_infos[i]['number'] > 0:
                macro_code = macros_infos[i]['function'](code)
                for i in macro_code:
                    for j in i:
                        report_vba += j

        vbaparser.close()
        return report_vba
コード例 #24
0
    def check_for_macros(self, filename, file_contents, request_hash):
        # noinspection PyBroadException
        try:
            vba_parser = VBA_Parser(filename=filename, data=file_contents)

            try:
                if vba_parser.detect_vba_macros():
                    self.ole_result.add_tag(TAG_TYPE.TECHNIQUE_MACROS,
                                            "Contains VBA Macro(s)",
                                            weight=TAG_WEIGHT.LOW,
                                            usage=TAG_USAGE.IDENTIFICATION)

                    try:
                        for (subfilename, stream_path, vba_filename, vba_code) in vba_parser.extract_macros():
                            if vba_code.strip() == '':
                                continue
                            vba_code_sha256 = hashlib.sha256(vba_code).hexdigest()
                            if vba_code_sha256 == request_hash:
                                continue

                            self.all_vba.append(vba_code)
                            macro_section = self.macro_section_builder(vba_code)
                            toplevel_score = self.calculate_nested_scores(macro_section)

                            self.all_macros.append(Macro(vba_code, vba_code_sha256, macro_section, toplevel_score))
                    except Exception as e:
                        self.log.debug("OleVBA VBA_Parser.extract_macros failed: {}".format(str(e)))
                        section = ResultSection(SCORE.NULL, "OleVBA : Error extracting macros")
                        self.ole_result.add_section(section)

            except Exception as e:
                self.log.debug("OleVBA VBA_Parser.detect_vba_macros failed: {}".format(e))
                section = ResultSection(SCORE.NULL, "OleVBA : Error parsing macros: {}".format(e))
                self.ole_result.add_section(section)
        except:
            self.log.debug("OleVBA VBA_Parser constructor failed, may not be a supported OLE document")
コード例 #25
0
def process_file(container, filename, data, altparser=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)
        print 'Type:', vba.type
        if vba.detect_vba_macros():
            #print 'Contains VBA Macros:'
            for (subfilename, stream_path, vba_filename,
                 vba_code) in vba.extract_macros():
                # hide attribute lines:
                #TODO: option to disable attribute filtering
                vba_code_filtered = filter_vba(vba_code)
                print '-' * 79
                print 'VBA MACRO %s ' % vba_filename
                print 'in file: %s - OLE stream: %s' % (subfilename,
                                                        repr(stream_path))
                print '- ' * 39
                # detect empty macros:
                if vba_code_filtered.strip() == '':
                    print '(empty macro)'
                else:
                    # TODO: option to display code
                    vba_code = vba_collapse_long_lines(vba_code)
                    print '-' * 79
                    print 'VBA CODE (with long lines collapsed):'
                    print vba_code
                    print '-' * 79
                    print 'PARSING VBA CODE:'
                    try:
                        if altparser:
                            vm.add_module2(vba_code)
                        else:
                            vm.add_module(vba_code)
                    except ParseException as err:
                        print err.line
                        print " " * (err.column - 1) + "^"
                        print err

            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 ''
コード例 #26
0
ファイル: office.py プロジェクト: xorhex/viper-modules
    def parse_vba(self, save_path):
        """
        Parse VBA scripts.
        """
        save = False
        vbaparser = VBA_Parser(__sessions__.current.file.path)
        # Check for Macros
        if not vbaparser.detect_vba_macros():
            self.log("error", "No macros detected")
            return
        self.log("info", "Macros detected")
        # try:
        if True:
            an_results = {
                "AutoExec": [],
                "Suspicious": [],
                "IOC": [],
                "Hex String": [],
                "Base64 String": [],
                "Dridex string": [],
                "VBA string": []
            }
            for (filename, stream_path, vba_filename,
                 vba_code) in vbaparser.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)))
                # Analyse the VBA Code
                vba_scanner = VBA_Scanner(vba_code)
                analysis = vba_scanner.scan(include_decoded_strings=True)
                for kw_type, keyword, description in analysis:
                    an_results[kw_type].append(
                        [string_clean_hex(keyword), description])

                # Save the code to external File
                if save_path:
                    try:
                        with open(save_path, "a") as out:
                            out.write(vba_code)
                        save = True
                    except Exception as e:
                        self.log(
                            "error",
                            "Unable to write to {0}: {1}".format(save_path, e))
                        return

            # Print all tables together
            if an_results["AutoExec"]:
                self.log("info", "Autorun macros found")
                self.log(
                    "table",
                    dict(header=["Method", "Description"],
                         rows=an_results["AutoExec"]))

            if an_results["Suspicious"]:
                self.log("info", "Suspicious keywords found")
                self.log(
                    "table",
                    dict(header=["Keyword", "Description"],
                         rows=an_results["Suspicious"]))

            if an_results["IOC"]:
                self.log("info", "Possible IOCs")
                self.log("table",
                         dict(header=["IOC", "Type"], rows=an_results["IOC"]))

            if an_results["Hex String"]:
                self.log("info", "Hex strings")
                self.log(
                    "table",
                    dict(header=["Decoded", "Raw"],
                         rows=an_results["Hex String"]))

            if an_results["Base64 String"]:
                self.log("info", "Base64 strings")
                self.log(
                    "table",
                    dict(header=["Decoded", "Raw"],
                         rows=an_results["Base64 String"]))

            if an_results["Dridex string"]:
                self.log("info", "Dridex strings")
                self.log(
                    "table",
                    dict(header=["Decoded", "Raw"],
                         rows=an_results["Dridex string"]))

            if an_results["VBA string"]:
                self.log("info", "VBA strings")
                self.log(
                    "table",
                    dict(header=["Decoded", "Raw"],
                         rows=an_results["VBA string"]))

            if save:
                self.log("success",
                         "Writing VBA Code to {0}".format(save_path))

        # Close the file
        vbaparser.close()
コード例 #27
0
ファイル: parse_office.py プロジェクト: kevoreilly/CAPEv2
    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
コード例 #28
0
def process_file_scanexpr (container, filename, data):
    """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
    safe_print('='*79)
    safe_print('FILE: ' + safe_str_convert(display_filename))
    all_code = ''
    try:
        #TODO: handle olefile errors, when an OLE file is malformed
        import oletools
        oletools.olevba.enable_logging()
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug('opening %r' % filename)
        vba = VBA_Parser(filename, data, relaxed=True)
        if vba.detect_vba_macros():

            # Read in document metadata.
            vm = core.ViperMonkey(filename, data)
            ole = olefile.OleFileIO(filename)
            try:
                vm.set_metadata(ole.get_metadata())
            except Exception as e:
                log.warning("Reading in metadata failed. Trying fallback. " + safe_str_convert(e))
                vm.set_metadata(get_metadata_exif(filename))
            
            #print 'Contains VBA Macros:'
            for (subfilename, stream_path, vba_filename, vba_code) in vba.extract_macros():
                # hide attribute lines:
                #TODO: option to disable attribute filtering
                vba_code = filter_vba(vba_code)
                safe_print('-'*79)
                safe_print('VBA MACRO %s ' % vba_filename)
                safe_print('in file: %s - OLE stream: %s' % (subfilename, repr(stream_path)))
                safe_print('- '*39)
                # detect empty macros:
                if vba_code.strip() == '':
                    safe_print('(empty macro)')
                else:
                    # TODO: option to display code
                    safe_print(vba_code)
                    vba_code = core.vba_collapse_long_lines(vba_code)
                    all_code += '\n' + vba_code
            safe_print('-'*79)
            safe_print('EVALUATED VBA EXPRESSIONS:')
            t = prettytable.PrettyTable(('Obfuscated expression', 'Evaluated value'))
            t.align = 'l'
            t.max_width['Obfuscated expression'] = 36
            t.max_width['Evaluated value'] = 36
            for expression, expr_eval in core.scan_expressions(all_code):
                t.add_row((repr(expression), repr(expr_eval)))
                safe_print(t)

        else:
            safe_print('No VBA macros found.')
    except Exception as e:
        log.error("Caught exception. " + safe_str_convert(e))
        if (log.getEffectiveLevel() == logging.DEBUG):
            traceback.print_exc()

    safe_print('')
コード例 #29
0
def run(analyzer_name, job_id, filepath, filename, md5,
        additional_config_params):
    logger.info("started analyzer {} job_id {}"
                "".format(analyzer_name, job_id))
    report = general.get_basic_report_template(analyzer_name)
    try:
        results = {}

        # olevba
        olevba_results = {}
        try:

            vbaparser = VBA_Parser(filepath)

            olevba_results[
                'macro_found'] = True if vbaparser.detect_vba_macros(
                ) else False

            if olevba_results['macro_found']:
                macro_data = []
                for (v_filename, stream_path, vba_filename,
                     vba_code) in vbaparser.extract_macros():
                    extracted_macro = {
                        "filename": v_filename,
                        "ole_stream": stream_path,
                        "vba_filename": vba_filename,
                        "vba_code": vba_code
                    }
                    macro_data.append(extracted_macro)
                olevba_results['macro_data'] = macro_data

                # example output
                '''
                {'description': 'Runs when the Word document is opened',
                 'keyword': 'AutoOpen',
                 'type': 'AutoExec'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'Shell',
                 'type': 'Suspicious'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'WScript.Shell',
                 'type': 'Suspicious'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'Run',
                 'type': 'Suspicious'},
                {'description': 'May run PowerShell commands',
                 'keyword': 'powershell',
                 'type': 'Suspicious'},
                {'description': '9BA55BE5', 'keyword': 'xxx', 'type': 'Hex String'},
                 '''
                analyzer_results = vbaparser.analyze_macros(
                    show_decoded_strings=True)
                # it gives None if it does not find anything
                if analyzer_results:
                    analyze_macro_results = []
                    for kw_type, keyword, description in analyzer_results:
                        if kw_type != 'Hex String':
                            analyze_macro_result = {
                                "type": kw_type,
                                "keyword": keyword,
                                "description": description
                            }
                            analyze_macro_results.append(analyze_macro_result)
                    olevba_results['analyze_macro'] = analyze_macro_results

                olevba_results['reveal'] = vbaparser.reveal()

            vbaparser.close()

        except Exception as e:
            traceback.print_exc()
            error_message = "job_id {} vba parser failed. Error: {}".format(
                job_id, e)
            logger.exception(error_message)
            report['errors'].append(error_message)

        results['olevba'] = olevba_results

        # mraptor
        macro_raptor = mraptor.MacroRaptor(olevba_results.get('reveal', ''))
        if macro_raptor:
            macro_raptor.scan()
            results[
                'mraptor'] = "suspicious" if macro_raptor.suspicious else 'ok'

        # pprint.pprint(results)
        report['report'] = results
    except AnalyzerRunException as e:
        error_message = "job_id:{} analyzer:{} md5:{} filename: {} Analyzer Error {}" \
                        "".format(job_id, analyzer_name, md5, filename, e)
        logger.error(error_message)
        report['errors'].append(error_message)
        report['success'] = False
    except Exception as e:
        traceback.print_exc()
        error_message = "job_id:{} analyzer:{} md5:{} filename: {} Unexpected Error {}" \
                        "".format(job_id, analyzer_name, md5, filename, e)
        logger.exception(error_message)
        report['errors'].append(str(e))
        report['success'] = False
    else:
        report['success'] = True

    general.set_report_and_cleanup(job_id, report, logger)

    logger.info("ended analyzer {} job_id {}" "".format(analyzer_name, job_id))

    return report
コード例 #30
0
class DocInfo(FileAnalyzer):
    def set_config(self, additional_config_params):
        self.olevba_results = {}
        self.vbaparser = None
        self.experimental = additional_config_params.get("experimental", False)
        self.passwords_to_check = []
        # this is to extract the passwords for encryption requested by the client
        # you can use pyintelowl to send additional passwords to check for
        # example:
        #             "additional_configuration": {
        #                 "Doc_Info_Experimental": {
        #                     "additional_passwords_to_check": ["testpassword"]
        #                 }
        #             },
        additional_passwords_to_check = additional_config_params.get(
            "additional_passwords_to_check", []
        )
        if isinstance(additional_passwords_to_check, list):
            self.passwords_to_check.extend(additional_passwords_to_check)

    def run(self):
        results = {}

        # olevba
        try:
            self.vbaparser = VBA_Parser(self.filepath)

            self.manage_encrypted_doc()

            if self.experimental:
                self.experimental_analysis()

            # go on with the normal oletools execution
            self.olevba_results["macro_found"] = self.vbaparser.detect_vba_macros()

            if self.olevba_results["macro_found"]:
                vba_code_all_modules = ""
                macro_data = []
                for (
                    v_filename,
                    stream_path,
                    vba_filename,
                    vba_code,
                ) in self.vbaparser.extract_macros():
                    extracted_macro = {
                        "filename": v_filename,
                        "ole_stream": stream_path,
                        "vba_filename": vba_filename,
                        "vba_code": vba_code,
                    }
                    macro_data.append(extracted_macro)
                    vba_code_all_modules += vba_code + "\n"
                self.olevba_results["macro_data"] = macro_data

                # example output
                #
                # {'description': 'Runs when the Word document is opened',
                #  'keyword': 'AutoOpen',
                #  'type': 'AutoExec'},
                # {'description': 'May run an executable file or a system command',
                #  'keyword': 'Shell',
                #  'type': 'Suspicious'},
                # {'description': 'May run an executable file or a system command',
                #  'keyword': 'WScript.Shell',
                #  'type': 'Suspicious'},
                # {'description': 'May run an executable file or a system command',
                #  'keyword': 'Run',
                #  'type': 'Suspicious'},
                # {'description': 'May run PowerShell commands',
                #  'keyword': 'powershell',
                #  'type': 'Suspicious'},
                # {'description': '9BA55BE5', 'keyword': 'xxx', 'type': 'Hex String'},

                # mraptor
                macro_raptor = mraptor.MacroRaptor(vba_code_all_modules)
                if macro_raptor:
                    macro_raptor.scan()
                    results["mraptor"] = (
                        "suspicious" if macro_raptor.suspicious else "ok"
                    )

                # analyze macros
                analyzer_results = self.vbaparser.analyze_macros()
                # it gives None if it does not find anything
                if analyzer_results:
                    analyze_macro_results = []
                    for kw_type, keyword, description in analyzer_results:
                        if kw_type != "Hex String":
                            analyze_macro_result = {
                                "type": kw_type,
                                "keyword": keyword,
                                "description": description,
                            }
                            analyze_macro_results.append(analyze_macro_result)
                    self.olevba_results["analyze_macro"] = analyze_macro_results

        except CannotDecryptException as e:
            logger.info(e)
        except Exception as e:
            error_message = f"job_id {self.job_id} vba parser failed. Error: {e}"
            logger.exception(error_message)
            self.report["errors"].append(error_message)
        finally:
            if self.vbaparser:
                self.vbaparser.close()

        results["olevba"] = self.olevba_results

        return results

    def manage_encrypted_doc(self):
        self.olevba_results["is_encrypted"] = False
        # checks if it is an OLE file. That could be encrypted
        if self.vbaparser.ole_file:
            # check if the ole file is encrypted
            is_encrypted = self.vbaparser.detect_is_encrypted()
            self.olevba_results["is_encrypted"] = is_encrypted
            # in the case the file is encrypted I try to decrypt it
            # with the default password and the most common ones
            if is_encrypted:
                # by default oletools contains some basic passwords
                # we just add some more guesses
                common_pwd_to_check = []
                for num in range(10):
                    common_pwd_to_check.append(f"{num}{num}{num}{num}")
                # https://twitter.com/JohnLaTwC/status/1265377724522131457
                filename_without_spaces_and_numbers = sub("[-_\d\s]", "", self.filename)
                filename_without_extension = sub(
                    "(\..+)", "", filename_without_spaces_and_numbers
                )
                common_pwd_to_check.append(filename_without_extension)
                self.passwords_to_check.extend(common_pwd_to_check)
                decrypted_file_name = self.vbaparser.decrypt_file(
                    self.passwords_to_check
                )
                self.olevba_results[
                    "additional_passwords_tried"
                ] = self.passwords_to_check
                if decrypted_file_name:
                    self.vbaparser = VBA_Parser(decrypted_file_name)
                else:
                    self.olevba_results["cannot_decrypt"] = True
                    raise CannotDecryptException(
                        "cannot decrypt the file with the default password"
                    )

    def experimental_analysis(self):
        self.manage_xlm_macros()

    def manage_xlm_macros(self):
        self.olevba_results["xlm_macro"] = False
        # check if the file contains an XLM macro
        # and try an experimental parsing
        # credits to https://twitter.com/gabriele_pippi for the idea
        if self.vbaparser.detect_xlm_macros():
            self.olevba_results["xlm_macro"] = True
            logger.debug("experimental XLM macro analysis start")
            parsed_file = b""
            try:
                excel_doc = XLSWrapper2(self.filepath)
                ae_list = [
                    "auto_open",
                    "auto_close",
                    "auto_activate",
                    "auto_deactivate",
                ]
                self.olevba_results["xlm_macro_autoexec"] = []
                for ae in ae_list:
                    auto_exec_labels = excel_doc.get_defined_name(ae, full_match=False)
                    for label in auto_exec_labels:
                        self.olevba_results["xlm_macro_autoexec"].append(label[0])

                for i in show_cells(excel_doc):
                    rec_str = ""
                    if len(i) == 5:
                        # rec_str = 'CELL:{:10}, {:20}, {}'
                        # .format(i[0].get_local_address(), i[2], i[4])
                        if i[2] != "None":
                            rec_str = "{:20}".format(i[2])
                    if rec_str:
                        parsed_file += rec_str.encode()
                        parsed_file += b"\n"
            except Exception as e:
                logger.info(f"experimental XLM macro analysis failed. Exception: {e}")
            else:
                logger.debug(
                    f"experimental XLM macro analysis succeded. "
                    f"Binary to analyze: {parsed_file}"
                )
                if parsed_file:
                    self.vbaparser = VBA_Parser(self.filename, data=parsed_file)
コード例 #31
0
def POE(logdir, targetfile, logging, debug):

    if (logging == True):
        LOG = logger()
    newlogentry = ''
    macro_dump_data = ''

    FI = fileio()

    try:
        filedata = open(targetfile.filename, 'rb').read()
        vbaparser = VBA_Parser(targetfile.filename, data=filedata)
        if vbaparser.detect_vba_macros():
            print '[*] VBA macros found - Extracting...\n'
            if (logging == True):
                newlogentry = 'VBA macros found - Extracting...'
                LOG.WriteLog(logdir, targetfile.filename, newlogentry)
            for (filename, stream_path, vba_filename,
                 vba_code) in vbaparser.extract_macros():
                macro_dump_data += '-' * 79 + '\n'
                try:
                    macro_dump_data += 'Filename    :' + filename.encode(
                        "ascii", "replace") + '\n'
                    macro_dump_data += 'OLE stream  :' + stream_path.encode(
                        "ascii", "replace") + '\n'
                    macro_dump_data += 'VBA filename:' + vba_filename.encode(
                        "ascii", "replace") + '\n'
                except Exception, e:
                    print '[x] Current macro - unable to print Filename, OLE stream or VBA filename due to encoding issue (Unicode?): ', e
                macro_dump_data += '-' * 79 + '\n'
                macro_dump_data += vba_code
                FI.WriteLogFile(logdir + vba_filename, macro_dump_data)

                try:
                    print '[*] Macro ' + vba_filename.encode(
                        "ascii", "replace"
                    ) + ' extracted to: ' + logdir + vba_filename.encode(
                        "ascii", "replace")
                    targetfile.macros.append(
                        logdir + vba_filename.encode("ascii", "replace"))

                    if (logging == True):
                        newlogentry = 'Macro ' + vba_filename.encode(
                            "ascii", "replace"
                        ) + ' extracted to: <a href=\"' + logdir + vba_filename.encode(
                            "ascii", "replace") + '\">' + vba_filename.encode(
                                "ascii", "replace") + '</a>'
                    LOG.WriteLog(logdir, targetfile.filename, newlogentry)
                    if (debug == True):
                        print '-' * 79
                        print 'Filename    :', filename.encode(
                            "ascii", "replace")
                        print 'OLE stream  :', stream_path.encode(
                            "ascii", "replace")
                        print 'VBA filename:', vba_filename.encode(
                            "utf-8", "ignore")
                        print '-' * 79
                except Exception, e:
                    print '[x] Current macro - unable print Filename, OLE stream or VBA filename due to encoding issue: (Unicode?)', e

                if (debug == True):
                    print vba_code

                macro_dump_data = ''
            print 'Macro List'
            for mlist in targetfile.macros:
                print mlist
コード例 #32
0
      from oletools.olevba import VBA_Parser
else:
     #python 3
	  from oletools.olevba3 import VBA_Parser

# VBA 퍼져 온 
vbaparser = VBA_Parser(sys.argv[1])
  # 매크로 검사
if not vbaparser.detect_vba_macros():
 print ('error', "macro not detected ")
 #경고모듈 넣는 위치 
 sys.exit(1)

print ('info', "macro detected ! ")

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:
コード例 #33
0
        description='Analyze docx document (pretty limited for now)')
    parser.add_argument('FILE', help='Docx document')
    args = parser.parse_args()

    if not os.path.isfile(args.FILE):
        print("Invalid file path")
        sys.exit(1)

    # Check if any macro and extract it
    vbaparser = VBA_Parser(args.FILE)
    if vbaparser.detect_vba_macros():
        print('VBA Macros found')
        mac_name = os.path.splitext(args.FILE)[0] + '.macro'
        with open(mac_name, 'w+') as f:
            for (filename, stream_path, vba_filename,
                 vba_code) in vbaparser.extract_macros():
                f.write(vba_code)
                f.write('\n')
        print("Macro dumped in {}".format(mac_name))
    else:
        print('No VBA Macros found')

    # Show metadata
    input_zip = ZipFile(args.FILE)
    print("")
    print("Metadata:")
    for d in extract_metadata(input_zip):
        print("-{} : {}".format(*d))

    # Analyze types of files
    print("")
コード例 #34
0
ファイル: module_office.py プロジェクト: jdubp/FileScanner
def parse_vba(file):
	print_output(file, '\n\n-----------------------------------------\n[Analyzing with olevba]\n-----------------------------------------\n', 'text')
	ole_macro_result = 'no vb-macro'    
	has_macros = False
	
	indicators = []
	macro_indicators = []	
	
	vbaparser = VBA_Parser(filescanner_proc_dir+file)
	# Check for Macros
	if not vbaparser.detect_vba_macros():
		print_output(file, '[-] No Macros Found', 'text') 
		return has_macros, ole_macro_result, indicators

	if True:
		print_output(file, '[-] MACROS FOUND', 'text')   
		has_macros = True
		ole_macro_result = 'VB-MACRO FOUND'     
		
		# Variable to be passed to MacroRaptor    
		vba_code_all_modules = ''
	
		for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_all_macros():
			vba_code_all_modules += vba_code + '\n'        
		
		for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
			print_output(file, '\nOLE Stream: {0}'.format(string_clean(stream_path)), 'text')
			print_output(file, 'VBA Filename: {0}'.format(string_clean(vba_filename)), 'text')            
			# Analyse the VBA Code      
			results = vbaparser.analyze_macros(show_decoded_strings=True)
			for kw_type, keyword, description in results:                
				# Add IOC detections to indicators list
				if kw_type == 'IOC':            
					indicators.append(description+': '+keyword)
					print_output(file, '{} - {} - {}'.format(kw_type, keyword, description), 'shell')
					
				else:            
					print_output(file, '{} - {} - {}'.format(kw_type, keyword, description), 'text')					

			# Deobfusgate and return macro code
			# print_output(file, '\n'+vbaparser.reveal(), 'text')
			
		# Print number of items in each category and append to indicators list
		print_output(file, '', 'shell')       
		print_output(file, 'AutoExec keywords: {}'.format(vbaparser.nb_autoexec), 'shell')
		if vbaparser.nb_autoexec != 0: 
			indicators.append('AutoExec keywords: {}'.format(vbaparser.nb_autoexec)) 	
			
		print_output(file, 'Suspicious keywords: {}'.format(vbaparser.nb_suspicious), 'shell')
		if vbaparser.nb_suspicious != 0: 
			indicators.append('Suspicious keywords: {}'.format(vbaparser.nb_suspicious)) 		
		
		print_output(file, 'IOCs: {}'.format(vbaparser.nb_iocs), 'shell')
		
		print_output(file, 'Hex obfuscated strings: {}'.format(vbaparser.nb_hexstrings), 'shell')
		if vbaparser.nb_hexstrings != 0: 
			indicators.append('Hex obfuscated strings: {}'.format(vbaparser.nb_hexstrings)) 		
		
		print_output(file, 'Base64 obfuscated strings: {}'.format(vbaparser.nb_base64strings), 'shell')
		if vbaparser.nb_base64strings != 0: 
			indicators.append('Base64 obfuscated strings: {}'.format(vbaparser.nb_base64strings)) 		
		
		print_output(file, 'Dridex obfuscated strings: {}'.format(vbaparser.nb_dridexstrings), 'shell')
		if vbaparser.nb_dridexstrings != 0: 
			indicators.append('Dridex obfuscated strings: {}'.format(vbaparser.nb_dridexstrings)) 		
		
		print_output(file, 'VBA obfuscated strings: {}'.format(vbaparser.nb_vbastrings), 'shell')  
		if vbaparser.nb_vbastrings != 0: 
			indicators.append('VBA obfuscated strings: {}'.format(vbaparser.nb_vbastrings)) 
		
		# Update indicators list with matches from MRaptor
		macro_indicators = scan_macro(file, vba_code_all_modules)
		indicators = indicators + macro_indicators
		
		# Use oledump to gather VBA code for archiving		
		oledump_scan(file, '-p plugin_vba_summary.py')
		
	# Close the file
	vbaparser.close()   
	
	return has_macros, ole_macro_result, indicators
コード例 #35
0
    def run(self):
        results = {}
        # olevba
        olevba_results = {}
        try:
            vbaparser = VBA_Parser(self.filepath)

            olevba_results["macro_found"] = (
                True if vbaparser.detect_vba_macros() else False
            )

            if olevba_results["macro_found"]:
                macro_data = []
                for (
                    v_filename,
                    stream_path,
                    vba_filename,
                    vba_code,
                ) in vbaparser.extract_macros():
                    extracted_macro = {
                        "filename": v_filename,
                        "ole_stream": stream_path,
                        "vba_filename": vba_filename,
                        "vba_code": vba_code,
                    }
                    macro_data.append(extracted_macro)
                olevba_results["macro_data"] = macro_data

                # example output
                """
                {'description': 'Runs when the Word document is opened',
                 'keyword': 'AutoOpen',
                 'type': 'AutoExec'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'Shell',
                 'type': 'Suspicious'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'WScript.Shell',
                 'type': 'Suspicious'},
                {'description': 'May run an executable file or a system command',
                 'keyword': 'Run',
                 'type': 'Suspicious'},
                {'description': 'May run PowerShell commands',
                 'keyword': 'powershell',
                 'type': 'Suspicious'},
                {'description': '9BA55BE5', 'keyword': 'xxx', 'type': 'Hex String'},
                 """
                analyzer_results = vbaparser.analyze_macros(show_decoded_strings=True)
                # it gives None if it does not find anything
                if analyzer_results:
                    analyze_macro_results = []
                    for kw_type, keyword, description in analyzer_results:
                        if kw_type != "Hex String":
                            analyze_macro_result = {
                                "type": kw_type,
                                "keyword": keyword,
                                "description": description,
                            }
                            analyze_macro_results.append(analyze_macro_result)
                    olevba_results["analyze_macro"] = analyze_macro_results

                olevba_results["reveal"] = vbaparser.reveal()

            vbaparser.close()

        except Exception as e:
            traceback.print_exc()
            error_message = f"job_id {self.job_id} vba parser failed. Error: {e}"
            logger.exception(error_message)
            self.report["errors"].append(error_message)

        results["olevba"] = olevba_results

        # mraptor
        macro_raptor = mraptor.MacroRaptor(olevba_results.get("reveal", None))
        if macro_raptor:
            macro_raptor.scan()
            results["mraptor"] = "suspicious" if macro_raptor.suspicious else "ok"

        return results
コード例 #36
0
ファイル: officeparse.py プロジェクト: Tigzy/malware-repo
def ProcessFile(path):
    if not(os.path.isfile(path)):
        print '{0} not a file!'.format(path)
        return 2

    try:
        data = {}
        data['valid'] = True  
        oledata = {}
        
        vbaparser = VBA_Parser(path)
        oledata['has_macros'] = vbaparser.detect_vba_macros()
        
        # dump macros content
        macros = []
        for (filename, stream_path, vba_filename, vba_code) in vbaparser.extract_macros():
            macro = {}
            macro['filename']   = filename
            macro['stream']     = stream_path
            macro['vba']        = vba_filename
            macro['content']    = convert_to_printable_null_terminated(vba_code)
            macros.append(macro)
        oledata['macros'] = macros
            
        # macro analysis
        macros_warnings = []
        results = vbaparser.analyze_macros()
        for kw_type, keyword, description in results:
            warning = {}
            warning['type']         = kw_type
            warning['keyword']      = keyword
            warning['description']  = description
            macros_warnings.append(warning)
        oledata['macros_warnings'] = macros_warnings
            
        # counters
        counters = {}
        counters['autoexec']           = vbaparser.nb_autoexec
        counters['suspicious']         = vbaparser.nb_suspicious
        counters['iocs']               = vbaparser.nb_iocs
        counters['hexstrings']         = vbaparser.nb_hexstrings
        counters['base64strings']      = vbaparser.nb_base64strings
        counters['dridexstrings']      = vbaparser.nb_dridexstrings
        counters['vbastrings']         = vbaparser.nb_vbastrings
        oledata['counters']            = counters    
        
        # deobfuscation    
        oledata['deobfuscated'] = convert_to_printable_null_terminated(vbaparser.reveal())
        
        # close
        vbaparser.close()
        
        data['data'] = oledata
        encoded = json.dumps(data)
        print encoded
    except Exception as ex:
        data = {}
        data['valid'] = False
        data['error'] = str(ex)
        print json.dumps(data)
        return 1
        
    return 0