Ejemplo n.º 1
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
Ejemplo n.º 2
0
def compile_input_file(input_file: str) -> Program:
    path = Path(input_file)

    if path.is_dir():
        # A directory must be a project containing VBA source files
        return Compiler.compile_project(input_file)

    with open(input_file, "rb") as f:
        content = f.read()

    # Try to deserialize an already compiled program
    try:
        serializer = Serializer()
        obj = serializer.deserialize(content)

        if type(obj) == Program:
            return obj
    except SerializationError:
        pass

    # Compile an Office document or VBA source files
    units = []
    if magic_from_buffer(content, mime=True) == "text/plain":
        if not input_file.endswith(".vbs"):
            input_file += ".vbs"
        units.append(Unit.from_content(content.decode("utf-8"), input_file))
    else:
        vba_parser = VBA_Parser(input_file, data=content)

        for _, _, vba_filename, vba_code in vba_parser.extract_all_macros():
            units.append(Unit.from_content(vba_code, vba_filename))

    return Compiler.compile_units(units)
Ejemplo n.º 3
0
def extract_macros_from_office2003(fullpath, fileobj=None):
    '''

    :return: [(host_fullpath, filename_from_host, data), ... ]
    '''
    from oletools.olevba import VBA_Parser

    vp = VBA_Parser(fullpath, data=fileobj.read() if fileobj else None)

    r = []

    try:
        if vp.detect_vba_macros():
            macros = vp.extract_all_macros()
            assert (macros
                    )  # macros detect, if cannot extact, must be error occured
            if macros:
                for (subfullpath, stream_path, vba_filename,
                     vba_code) in macros:
                    a = os.path.basename(fullpath)
                    b = os.path.basename(subfullpath)
                    vba_filename += u'.vba'
                    sub = (io_text_arg(fullpath),
                           io_text_arg(vba_filename if a == b else u'{0}_{1}'.
                                       format(b, vba_filename)), vba_code)
                    r.append(sub)
    except:
        pass
    finally:
        vp.close()

    return r
Ejemplo n.º 4
0
 def get_macro(self):
     """
     Get Macros from an Office file and write them to a text file
     """
     try:
         self.mk_tmp_dir()
         print "Getting Macros from {}".format(self.file)
         vb = VBA_Parser(self.file, relaxed=True)
         if vb.detect_vba_macros():
             with open("{}{}macros.txt".format(self.tmp_dir, os.sep), "w") as macro_file:
                 for (subfilename, stream_path, vba_filename, vba_code) in vb.extract_all_macros():
                     macro_file.write(vba_code)
     except Exception as e:
         print "get_macro Exception: {}".format(e)
Ejemplo n.º 5
0
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
Ejemplo n.º 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