def parse(workbook_path): vba_path = workbook_path + '.vba' vba_parser = VBA_Parser(workbook_path) vba_modules = vba_parser.extract_all_macros( ) if vba_parser.detect_vba_macros() else [] for _, _, _, content in vba_modules: decoded_content = content.decode('latin-1') lines = [] if '\r\n' in decoded_content: lines = decoded_content.split('\r\n') else: lines = decoded_content.split('\n') if lines: name = lines[0].replace('Attribute VB_Name = ', '').strip('"') content = [ line for line in lines[1:] if not (line.startswith('Attribute') and 'VB_' in line) ] if content and content[-1] == '': content.pop(len(content) - 1) lines_of_code = len(content) non_empty_lines_of_code = len([c for c in content if c]) if non_empty_lines_of_code > 0: if not os.path.exists(os.path.join(vba_path)): os.makedirs(vba_path) with open(os.path.join(vba_path, name + '.bas'), 'w') as f: f.write('\n'.join(content))
def get_result(filename): try: behavior = {} vbaparser = VBA_Parser(filename) if vbaparser.detect_vba_macros(): results = vbaparser.analyze_macros() for item in results: details = re.sub(r'\(.*\)', '', str(item[2])) details = details.replace('strings', 'str') details = re.sub(r' $', '', details) if item[0] == 'AutoExec': behavior.update({item[1]: details}) if item[0] == 'Suspicious': behavior.update({item[1]: details}) macro = vbaparser.reveal() attributes = re.findall(r'Attribute VB.*', macro, flags=re.MULTILINE) macro = re.sub(r'Attribute VB.*', '', macro) return {"behavior": behavior, "macro": macro, "attributes": attributes} vbaparser.close() except: return {}
def get_result(filename): try: behavior = {} vbaparser = VBA_Parser(filename) if vbaparser.detect_vba_macros(): results = vbaparser.analyze_macros() for item in results: details = re.sub(r'\(.*\)', '', str(item[2])) details = details.replace('strings', 'str') details = re.sub(r' $', '', details) if item[0] == 'AutoExec': behavior.update({item[1]: details}) if item[0] == 'Suspicious': behavior.update({item[1]: details}) macro = vbaparser.reveal() attributes = re.findall(r'Attribute VB.*', macro, flags=re.MULTILINE) macro = re.sub(r'Attribute VB.*', '', macro) vbaparser.close() return { "behavior": behavior, "macro": macro, "attributes": attributes } except: return {}
def parse(workbook_path): # vba_path = 'src.vba' vba_path = workbook_path + '.vba' vba_parser = VBA_Parser(workbook_path) vba_modules = vba_parser.extract_all_macros( ) if vba_parser.detect_vba_macros() else [] for _, _, filename, content in vba_modules: # decoded_content = content.decode('latin-1') decoded_content = content lines = [] if '\r\n' in decoded_content: lines = decoded_content.split('\r\n') else: lines = decoded_content.split('\n') if lines: content = [] for line in lines: if line.startswith('Attribute') and 'VB_' in line: if 'VB_Name' in line and KEEP_NAME: content.append(line) else: content.append(line) if content and content[-1] == '': content.pop(len(content) - 1) non_empty_lines_of_code = len([c for c in content if c]) if non_empty_lines_of_code > 0: if not os.path.exists(os.path.join(vba_path)): os.makedirs(vba_path) with open(os.path.join(vba_path, filename), 'w', encoding='utf-8') as f: f.write('\n'.join(content))
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, 'ab') as out: out.write(vba_code) save = True except Exception: 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 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, 'ab') 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 get_vba(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 try: vbaparser = VBA_Parser('mmbot', data=filedata) pathnames = '' 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")) 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 })
def get_vba(workbook): vba_parser = VBA_Parser(workbook) vba_modules = vba_parser.extract_all_macros() if vba_parser.detect_vba_macros() else [] modules = {} for _, _, _, content in vba_modules: decoded_content = content.decode('latin-1') lines = [] if '\r\n' in decoded_content: lines = decoded_content.split('\r\n') else: lines = decoded_content.split('\n') if lines: name = lines[0].replace('Attribute VB_Name = ', '').strip('"') content = [line for line in lines[1:] if not ( line.startswith('Attribute') and 'VB_' in line)] non_empty_lines_of_code = len([c for c in content if c]) modules[name] = '\n'.join(content) return modules