def main(): """ Main function, called when olevba is run from the command line """ global log DEFAULT_LOG_LEVEL = "warning" # Default log level LOG_LEVELS = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL } usage = 'usage: %prog [options] <filename> [filename2 ...]' parser = optparse.OptionParser(usage=usage) parser.add_option("-r", action="store_true", dest="recursive", help='find files recursively in subdirectories.') parser.add_option( "-z", "--zip", dest='zip_password', type='str', default=None, help= 'if the file is a zip archive, open all files from it, using the provided password (requires Python 2.6+)' ) parser.add_option( "-f", "--zipfname", dest='zip_fname', type='str', default='*', help= 'if the file is a zip archive, file(s) to be opened within the zip. Wildcards * and ? are supported. (default:*)' ) parser.add_option( '-l', '--loglevel', dest="loglevel", action="store", default=DEFAULT_LOG_LEVEL, help= "logging level debug/info/warning/error/critical (default=%default)") parser.add_option("-m", '--matches', action="store_true", dest="show_matches", help='Show matched strings.') # TODO: add logfile option (options, args) = parser.parse_args() # Print help if no arguments are passed if len(args) == 0: print __doc__ parser.print_help() print '\nAn exit code is returned based on the analysis result:' for result in (Result_NoMacro, Result_NotMSOffice, Result_MacroOK, Result_Error, Result_Suspicious): print ' - %d: %s' % (result.exit_code, result.name) sys.exit() # print banner with version print 'MacroRaptor %s - http://decalage.info/python/oletools' % __version__ print 'This is work in progress, please report issues at %s' % URL_ISSUES logging.basicConfig(level=LOG_LEVELS[options.loglevel], format='%(levelname)-8s %(message)s') # enable logging in the modules: log.setLevel(logging.NOTSET) t = tablestream.TableStream(style=tablestream.TableStyleSlim, header_row=['Result', 'Flags', 'Type', 'File'], column_width=[10, 5, 4, 56]) exitcode = -1 global_result = None # TODO: handle errors in xglob, to continue processing the next files for container, filename, data in xglob.iter_files( args, recursive=options.recursive, zip_password=options.zip_password, zip_fname=options.zip_fname): # ignore directory names stored in zip files: if container and filename.endswith('/'): continue full_name = '%s in %s' % (filename, container) if container else filename # try: # # Open the file # if data is None: # data = open(filename, 'rb').read() # except: # log.exception('Error when opening file %r' % full_name) # continue if isinstance(data, Exception): result = Result_Error t.write_row([result.name, '', '', full_name], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(data)], colors=[None, None, None, result.color]) else: filetype = '???' try: vba_parser = olevba.VBA_Parser(filename=filename, data=data, container=container) filetype = TYPE2TAG[vba_parser.type] except Exception as e: # log.error('Error when parsing VBA macros from file %r' % full_name) # TODO: distinguish actual errors from non-MSOffice files result = Result_Error t.write_row([result.name, '', filetype, full_name], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(e)], colors=[None, None, None, result.color]) continue if vba_parser.detect_vba_macros(): vba_code_all_modules = '' try: for (subfilename, stream_path, vba_filename, vba_code) in vba_parser.extract_all_macros(): vba_code_all_modules += vba_code + '\n' except Exception as e: # log.error('Error when parsing VBA macros from file %r' % full_name) result = Result_Error t.write_row([ result.name, '', TYPE2TAG[vba_parser.type], full_name ], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(e)], colors=[None, None, None, result.color]) continue mraptor = MacroRaptor(vba_code_all_modules) mraptor.scan() if mraptor.suspicious: result = Result_Suspicious else: result = Result_MacroOK t.write_row( [result.name, mraptor.get_flags(), filetype, full_name], colors=[result.color, None, None, None]) if mraptor.matches and options.show_matches: t.write_row(['', '', '', 'Matches: %r' % mraptor.matches]) else: result = Result_NoMacro t.write_row([result.name, '', filetype, full_name], colors=[result.color, None, None, None]) if result.exit_code > exitcode: global_result = result exitcode = result.exit_code print '' print 'Flags: A=AutoExec, W=Write, X=Execute' print 'Exit code: %d - %s' % (exitcode, global_result.name) sys.exit(exitcode)
def main(): # print banner with version print('rtfobj %s - http://decalage.info/python/oletools' % __version__) print('THIS IS WORK IN PROGRESS - Check updates regularly!') print( 'Please report any issue at https://github.com/decalage2/oletools/issues' ) print('') DEFAULT_LOG_LEVEL = "warning" # Default log level LOG_LEVELS = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL } usage = 'usage: %prog [options] <filename> [filename2 ...]' parser = optparse.OptionParser(usage=usage) # parser.add_option('-o', '--outfile', dest='outfile', # help='output file') # parser.add_option('-c', '--csv', dest='csv', # help='export results to a CSV file') parser.add_option("-r", action="store_true", dest="recursive", help='find files recursively in subdirectories.') parser.add_option( "-z", "--zip", dest='zip_password', type='str', default=None, help= 'if the file is a zip archive, open first file from it, using the provided password (requires Python 2.6+)' ) parser.add_option( "-f", "--zipfname", dest='zip_fname', type='str', default='*', help= 'if the file is a zip archive, file(s) to be opened within the zip. Wildcards * and ? are supported. (default:*)' ) parser.add_option( '-l', '--loglevel', dest="loglevel", action="store", default=DEFAULT_LOG_LEVEL, help= "logging level debug/info/warning/error/critical (default=%default)") parser.add_option( "-s", "--save", dest='save_object', type='str', default=None, help= 'Save the object corresponding to the provided number to a file, for example "-s 2". Use "-s all" to save all objects at once.' ) # parser.add_option("-o", "--outfile", dest='outfile', type='str', default=None, # help='Filename to be used when saving an object to a file.') parser.add_option("-d", type="str", dest="output_dir", help='use specified directory to save output files.', default=None) # parser.add_option("--pkg", action="store_true", dest="save_pkg", # help='Save OLE Package binary data of extracted objects (file embedded into an OLE Package).') # parser.add_option("--ole", action="store_true", dest="save_ole", # help='Save OLE binary data of extracted objects (object data without the OLE container).') # parser.add_option("--raw", action="store_true", dest="save_raw", # help='Save raw binary data of extracted objects (decoded from hex, including the OLE container).') # parser.add_option("--hex", action="store_true", dest="save_hex", # help='Save raw hexadecimal data of extracted objects (including the OLE container).') (options, args) = parser.parse_args() # Print help if no arguments are passed if len(args) == 0: print(__doc__) parser.print_help() sys.exit() # Setup logging to the console: # here we use stdout instead of stderr by default, so that the output # can be redirected properly. logging.basicConfig(level=LOG_LEVELS[options.loglevel], stream=sys.stdout, format='%(levelname)-8s %(message)s') # enable logging in the modules: log.setLevel(logging.NOTSET) oleobj.log.setLevel(logging.NOTSET) for container, filename, data in xglob.iter_files( args, recursive=options.recursive, zip_password=options.zip_password, zip_fname=options.zip_fname): # ignore directory names stored in zip files: if container and filename.endswith('/'): continue process_file(container, filename, data, output_dir=options.output_dir, save_object=options.save_object)
help="logging level debug/info/warning/error/critical (default=%default)") (options, args) = parser.parse_args() # Print help if no arguments are passed if len(args) == 0: print (__doc__) parser.print_help() sys.exit() # Setup logging to the console: # here we use stdout instead of stderr by default, so that the output # can be redirected properly. logging.basicConfig(level=LOG_LEVELS[options.loglevel], stream=sys.stdout, format='%(levelname)-8s %(message)s') # enable logging in the modules: log.setLevel(logging.NOTSET) oleobj.log.setLevel(logging.NOTSET) for container, filename, data in xglob.iter_files(args, recursive=options.recursive, zip_password=options.zip_password, zip_fname=options.zip_fname): # ignore directory names stored in zip files: if container and filename.endswith('/'): continue process_file(container, filename, data, options.output_dir) # This code was developed while listening to The Mary Onettes "Lost"
default=DEFAULT_LOG_LEVEL, help= "logging level debug/info/warning/error/critical (default=%default)") (options, args) = parser.parse_args() # Print help if no arguments are passed if len(args) == 0: print(__doc__) parser.print_help() sys.exit() # Setup logging to the console: # here we use stdout instead of stderr by default, so that the output # can be redirected properly. logging.basicConfig(level=LOG_LEVELS[options.loglevel], stream=sys.stdout, format='%(levelname)-8s %(message)s') # enable logging in the modules: log.setLevel(logging.NOTSET) for container, filename, data in xglob.iter_files( args, recursive=options.recursive, zip_password=options.zip_password, zip_fname=options.zip_fname): # ignore directory names stored in zip files: if container and filename.endswith('/'): continue process_file(container, filename, data, options.output_dir)
def main(): """ Main function, called when olevba is run from the command line """ global log DEFAULT_LOG_LEVEL = "warning" # Default log level LOG_LEVELS = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL } usage = 'usage: %prog [options] <filename> [filename2 ...]' parser = optparse.OptionParser(usage=usage) parser.add_option("-r", action="store_true", dest="recursive", help='find files recursively in subdirectories.') parser.add_option("-z", "--zip", dest='zip_password', type='str', default=None, help='if the file is a zip archive, open all files from it, using the provided password (requires Python 2.6+)') parser.add_option("-f", "--zipfname", dest='zip_fname', type='str', default='*', help='if the file is a zip archive, file(s) to be opened within the zip. Wildcards * and ? are supported. (default:*)') parser.add_option('-l', '--loglevel', dest="loglevel", action="store", default=DEFAULT_LOG_LEVEL, help="logging level debug/info/warning/error/critical (default=%default)") parser.add_option("-m", '--matches', action="store_true", dest="show_matches", help='Show matched strings.') # TODO: add logfile option (options, args) = parser.parse_args() # Print help if no arguments are passed if len(args) == 0: print __doc__ parser.print_help() print '\nAn exit code is returned based on the analysis result:' for result in (Result_NoMacro, Result_NotMSOffice, Result_MacroOK, Result_Error, Result_Suspicious): print ' - %d: %s' % (result.exit_code, result.name) sys.exit() # print banner with version print 'MacroRaptor %s - http://decalage.info/python/oletools' % __version__ print 'This is work in progress, please report issues at %s' % URL_ISSUES logging.basicConfig(level=LOG_LEVELS[options.loglevel], format='%(levelname)-8s %(message)s') # enable logging in the modules: log.setLevel(logging.NOTSET) t = tablestream.TableStream(style=tablestream.TableStyleSlim, header_row=['Result', 'Flags', 'Type', 'File'], column_width=[10, 5, 4, 56]) exitcode = -1 global_result = None # TODO: handle errors in xglob, to continue processing the next files for container, filename, data in xglob.iter_files(args, recursive=options.recursive, zip_password=options.zip_password, zip_fname=options.zip_fname): # ignore directory names stored in zip files: if container and filename.endswith('/'): continue full_name = '%s in %s' % (filename, container) if container else filename # try: # # Open the file # if data is None: # data = open(filename, 'rb').read() # except: # log.exception('Error when opening file %r' % full_name) # continue if isinstance(data, Exception): result = Result_Error t.write_row([result.name, '', '', full_name], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(data)], colors=[None, None, None, result.color]) else: filetype = '???' try: vba_parser = olevba.VBA_Parser(filename=filename, data=data, container=container) filetype = TYPE2TAG[vba_parser.type] except Exception as e: # log.error('Error when parsing VBA macros from file %r' % full_name) # TODO: distinguish actual errors from non-MSOffice files result = Result_Error t.write_row([result.name, '', filetype, full_name], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(e)], colors=[None, None, None, result.color]) continue if vba_parser.detect_vba_macros(): vba_code_all_modules = '' try: for (subfilename, stream_path, vba_filename, vba_code) in vba_parser.extract_all_macros(): vba_code_all_modules += vba_code + '\n' except Exception as e: # log.error('Error when parsing VBA macros from file %r' % full_name) result = Result_Error t.write_row([result.name, '', TYPE2TAG[vba_parser.type], full_name], colors=[result.color, None, None, None]) t.write_row(['', '', '', str(e)], colors=[None, None, None, result.color]) continue mraptor = MacroRaptor(vba_code_all_modules) mraptor.scan() if mraptor.suspicious: result = Result_Suspicious else: result = Result_MacroOK t.write_row([result.name, mraptor.get_flags(), filetype, full_name], colors=[result.color, None, None, None]) if mraptor.matches and options.show_matches: t.write_row(['', '', '', 'Matches: %r' % mraptor.matches]) else: result = Result_NoMacro t.write_row([result.name, '', filetype, full_name], colors=[result.color, None, None, None]) if result.exit_code > exitcode: global_result = result exitcode = result.exit_code print '' print 'Flags: A=AutoExec, W=Write, X=Execute' print 'Exit code: %d - %s' % (exitcode, global_result.name) sys.exit(exitcode)