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()
def scan_macro(vba_code): SCAN = {} vba_scanner = VBA_Scanner(vba_code) results = vba_scanner.scan(include_decoded_strings=False) for key, subiter in itertools.groupby(results, operator.itemgetter(0)): groups = [] groups.extend(['%s: %s' % (desc[1], desc[2]) for desc in subiter]) SCAN['%s' % key] = groups if not SCAN: return 'No results from scan' return SCAN
def process(self, sample, tag): try: hashbot = Hasher(sample) mymagic = magic.Magic(mime=True) sample_info = self.identify_sample(oletools.oleid.OleID(sample)) vba = VBA_Parser(sample) # Extend the results of sample_info with extra data and add to Splunk sample_info['submit_date'] = int(time()) sample_info['filetype'] = mymagic.from_file(sample) sample_info['sample_type'] = 'office' sample_info['id_tag'] = tag sample_info['sha1'] = hashbot.get_sha1() sample_info['md5'] = hashbot.get_md5() indicators = dict() if self.doc_has_macros(vba): macro = self.macro_extraction(vba) data = VBA_Scanner(macro['vba_code']).scan(include_decoded_strings=False) i = 1 for kw_type, keyword, description in data: indicators[str(i)] = {'type':kw_type, 'keyword':keyword, 'description':description } i+=1 sample_info['indicators'] = indicators self.share_data(sample_info) self.store_sample(sample) except Exception, e: print "Error on",sample,e
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()
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: 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))
vba = VBA_Parser(filepath) result = {'Suspicious': False, 'Base64 Strings': False, 'Hex Strings': False, 'Version': olevbaVersion} except TypeError: result = {'Error': redir_err.getvalue() } json_data = json.dumps(result, indent=4) print json_data sys.exit() # set stderr back to original __stderr__ sys.stderr = sys.__stderr__ if vba.detect_vba_macros(): result['vba'] = 'VBA Macros found' streams = [] for (filename, stream_path, vba_filename, vba_code) in vba.extract_macros(): vba_scanner = VBA_Scanner(vba_code) scan_results = vba_scanner.scan(include_decoded_strings=False) vba_scan_results = [] for kw_type, keyword, description in scan_results: vba_scan_results.append({'type': kw_type, 'keyword': keyword, 'description': description}) if (kw_type == 'Suspicious'): result['Suspicious'] = True if (keyword == 'Base64 Strings'): result['Base64 Strings'] = True if (keyword == 'Hex Strings'): result['Hex Strings'] = True streams.append({'Filename': filename, 'OLE stream': stream_path, 'VBA filename': vba_filename, 'VBA code': vba_code, 'scan_result': vba_scan_results }) result['streams'] = streams else:
def macro_scorer(self, text): self.log.debug("Macro scorer running") score_section = None try: vba_scanner = VBA_Scanner(text) vba_scanner.scan(include_decoded_strings=True) for string in self.ADDITIONAL_SUSPICIOUS_KEYWORDS: if re.search(string, text, re.IGNORECASE): # play nice with detect_suspicious from olevba.py vba_scanner.suspicious_keywords.append((string, 'May download files from the Internet')) stringcount = len(vba_scanner.autoexec_keywords) + len(vba_scanner.suspicious_keywords) + \ len(vba_scanner.iocs) if stringcount > 0: score_section = ResultSection(SCORE.NULL, "Interesting macro strings found") if len(vba_scanner.autoexec_keywords) > 0: subsection = ResultSection(min(self.MAX_STRING_SCORE, SCORE.LOW * len(vba_scanner.autoexec_keywords)), "Autoexecution strings") for keyword, description in vba_scanner.autoexec_keywords: subsection.add_line(keyword) subsection.add_tag(TAG_TYPE.OLE_MACRO_SUSPICIOUS_STRINGS, keyword, TAG_WEIGHT.HIGH, usage=TAG_USAGE.IDENTIFICATION) score_section.add_section(subsection) if len(vba_scanner.suspicious_keywords) > 0: subsection = ResultSection(min(self.MAX_STRING_SCORE, SCORE.MED * len(vba_scanner.suspicious_keywords)), "Suspicious strings or functions") for keyword, description in vba_scanner.suspicious_keywords: subsection.add_line(keyword) subsection.add_tag(TAG_TYPE.OLE_MACRO_SUSPICIOUS_STRINGS, keyword, TAG_WEIGHT.HIGH, usage=TAG_USAGE.IDENTIFICATION) score_section.add_section(subsection) if len(vba_scanner.iocs) > 0: subsection = ResultSection(min(500, SCORE.MED * len(vba_scanner.iocs)), "Potential host or network IOCs") scored_macro_uri = False for keyword, description in vba_scanner.iocs: # olevba seems to have swapped the keyword for description during iocs extraction # this holds true until at least version 0.27 subsection.add_line("{}: {}".format(keyword, description)) desc_ip = self.ip_re.match(description) if self.parse_uri(description) is True: scored_macro_uri = True elif desc_ip: ip_str = desc_ip.group(1) if not is_ip_reserved(ip_str): scored_macro_uri = True subsection.add_tag(TAG_TYPE.NET_IP, ip_str, TAG_WEIGHT.HIGH, usage=TAG_USAGE.CORRELATION) score_section.add_section(subsection) if scored_macro_uri and self.scored_macro_uri is False: self.scored_macro_uri = True scored_uri_section = ResultSection(score=500, title_text="Found network indicator(s) within macros") self.ole_result.add_section(scored_uri_section) except Exception as e: self.log.debug("OleVBA VBA_Scanner constructor failed: {}".format(str(e))) return score_section
def olevba_info(self): try: __import__('imp').find_module('oletools') from oletools.olevba import VBA_Parser, VBA_Scanner from oletools.olevba import __version__ as olevbaVersion except ImportError: self.error('Import Error: Module oletools not found') # Redirect stderr to devnull in case input file is not a valid office document. When parsing a non valid # document VBA Parser raises an error to stderr. redir_err = sys.stderr = StringIO() try: vba = VBA_Parser(self.path) result = { 'Suspicious': False, 'Base64 Strings': False, 'Hex Strings': False, 'Version': olevbaVersion } except TypeError: self.error('File type error: ' + redir_err.getvalue()) # set stderr back to original __stderr__ sys.stderr = sys.__stderr__ if vba.detect_vba_macros(): result['vba'] = 'VBA Macros found' streams = [] for (filename, stream_path, vba_filename, vba_code) in vba.extract_macros(): vba_scanner = VBA_Scanner(vba_code) scan_results = vba_scanner.scan(include_decoded_strings=False) vba_scan_results = [] for kw_type, keyword, description in scan_results: vba_scan_results.append({ 'type': str(kw_type).encode('utf-8'), 'keyword': str(keyword).encode('utf-8'), 'description': str(description).encode('utf-8') }) if (kw_type == 'Suspicious'): result['Suspicious'] = True if (keyword == 'Base64 Strings'): result['Base64 Strings'] = True if (keyword == 'Hex Strings'): result['Hex Strings'] = True streams.append({ 'Filename': self.filename, 'OLE stream': stream_path, 'VBA filename': vba_filename.decode('unicode-escape').encode('utf-8'), 'VBA code': vba_code.decode('unicode-escape').encode('utf-8'), 'scan_result': vba_scan_results }) result['streams'] = streams else: result['vba'] = 'No VBA Macros found' return result
#details_path = os.path.join(macro_dir, 'macro_{0}.details'.format(macro_index)) #with codecs.open(details_path, 'w', encoding='unicode_escape') as fp: #try: #fp.write(u'filename: {0}\nstream_path: {1}\nvba_filename: {2}\n'.format( #filename, #stream_path, #unicode(vba_filename, 'unicode_escape'))) #except: #traceback.print_exc() #sys.stdout.write(details_path + '\n') macro_json['analysis'] = [] scanner = VBA_Scanner(vba_code) #analysis_path = os.path.join(macro_dir, 'macro_{0}.analysis'.format(macro_index)) kw_counts = {} # key = keyword, value = int #with open(analysis_path, 'w') as fp: for kw_type, keyword, description in scanner.scan( include_decoded_strings=True): macro_json['analysis'].append({ 'kw_type': unicode(kw_type, encoding='utf-8', errors='replace'), 'keyword': unicode( keyword, encoding='utf-8', errors='replace', ), 'description':