Commit 6641ac1ab37ac2842ceed687143f50f6a91002d1

Authored by Christian Herdtweck
1 parent 8b21d586

created exception ProcessingError, raise from process_... functions and handle in main

Showing 1 changed file with 101 additions and 88 deletions
oletools/olevba.py
... ... @@ -214,7 +214,6 @@ import optparse
214 214 import os.path
215 215 import binascii
216 216 import base64
217   -import traceback
218 217 import zlib
219 218 import email # for MHTML parsing
220 219 import string # for printable
... ... @@ -304,6 +303,16 @@ class FileOpenError(Exception):
304 303 self.filename = filename
305 304  
306 305  
  306 +class ProcessingError(Exception):
  307 + """ raised by VBA_Parser.process_file* functions """
  308 +
  309 + def __init__(self, filename, orig_exception):
  310 + super(ProcessingError, self).__init__(
  311 + 'Error processing file %s (%s)' % (filename, orig_exception))
  312 + self.filename = filename
  313 + self.orig_exception = orig_exception
  314 +
  315 +
307 316 class MsoExtractionError(RuntimeError):
308 317 """ raised by mso_file_extract if parsing MSO/ActiveMIME data failed """
309 318  
... ... @@ -2643,12 +2652,11 @@ class VBA_Parser_CLI(VBA_Parser):
2643 2652 print self.reveal()
2644 2653 else:
2645 2654 print 'No VBA macros found.'
2646   - except Exception: #TypeError:
2647   - #raise
2648   - #TODO: print more info if debug mode
2649   - #print sys.exc_value
2650   - # display the exception with full stack trace for debugging, but do not stop:
2651   - traceback.print_exc()
  2655 + except Exception as exc:
  2656 + # display the exception with full stack trace for debugging
  2657 + log.exception('Error processing file %s (%s)' % (self.filename, exc))
  2658 + log.debug('Traceback:', exc_info=True)
  2659 + raise ProcessingError(self.filename, exc)
2652 2660 print ''
2653 2661  
2654 2662  
... ... @@ -2710,12 +2718,11 @@ class VBA_Parser_CLI(VBA_Parser):
2710 2718 result['code_deobfuscated'] = self.reveal()
2711 2719 result['macros'] = macros
2712 2720 result['json_conversion_successful'] = True
2713   - except Exception: #TypeError:
2714   - #raise
2715   - #TODO: print more info if debug mode
2716   - #print sys.exc_value
2717   - # display the exception with full stack trace for debugging, but do not stop:
2718   - traceback.print_exc()
  2721 + except Exception as exc:
  2722 + # display the exception with full stack trace for debugging
  2723 + log.exception('Error processing file %s (%s)' % (self.filename, exc))
  2724 + log.debug('Traceback:', exc_info=True)
  2725 + raise ProcessingError(self.filename, exc)
2719 2726  
2720 2727 return result
2721 2728  
... ... @@ -2725,54 +2732,46 @@ class VBA_Parser_CLI(VBA_Parser):
2725 2732 Process a file in triage mode, showing only summary results on one line.
2726 2733 """
2727 2734 #TODO: replace print by writing to a provided output file (sys.stdout by default)
2728   - message = ''
2729 2735 try:
2730   - if self.type is not None:
2731   - #TODO: handle olefile errors, when an OLE file is malformed
2732   - if self.detect_vba_macros():
2733   - # print a waiting message only if the output is not redirected to a file:
2734   - if sys.stdout.isatty():
2735   - print 'Analysis...\r',
2736   - sys.stdout.flush()
2737   - self.analyze_macros(show_decoded_strings=show_decoded_strings,
2738   - deobfuscate=deobfuscate)
2739   - flags = TYPE2TAG[self.type]
2740   - macros = autoexec = suspicious = iocs = hexstrings = base64obf = dridex = vba_obf = '-'
2741   - if self.contains_macros: macros = 'M'
2742   - if self.nb_autoexec: autoexec = 'A'
2743   - if self.nb_suspicious: suspicious = 'S'
2744   - if self.nb_iocs: iocs = 'I'
2745   - if self.nb_hexstrings: hexstrings = 'H'
2746   - if self.nb_base64strings: base64obf = 'B'
2747   - if self.nb_dridexstrings: dridex = 'D'
2748   - if self.nb_vbastrings: vba_obf = 'V'
2749   - flags += '%s%s%s%s%s%s%s%s' % (macros, autoexec, suspicious, iocs, hexstrings,
2750   - base64obf, dridex, vba_obf)
2751   - # old table display:
2752   - # macros = autoexec = suspicious = iocs = hexstrings = 'no'
2753   - # if nb_macros: macros = 'YES:%d' % nb_macros
2754   - # if nb_autoexec: autoexec = 'YES:%d' % nb_autoexec
2755   - # if nb_suspicious: suspicious = 'YES:%d' % nb_suspicious
2756   - # if nb_iocs: iocs = 'YES:%d' % nb_iocs
2757   - # if nb_hexstrings: hexstrings = 'YES:%d' % nb_hexstrings
2758   - # # 2nd line = info
2759   - # print '%-8s %-7s %-7s %-7s %-7s %-7s' % (self.type, macros, autoexec, suspicious, iocs, hexstrings)
2760   - else:
2761   - # self.type==None
2762   - # file type not OLE nor OpenXML
2763   - flags = '?'
2764   - message = 'File format not supported'
2765   - except Exception:
2766   - # another error occurred
2767   - #raise
2768   - #TODO: print more info if debug mode
2769   - #TODO: distinguish real errors from incorrect file types
2770   - flags = '!ERROR'
2771   - message = sys.exc_value
2772   - line = '%-12s %s' % (flags, self.filename)
2773   - if message:
2774   - line += ' - %s' % message
2775   - print line
  2736 + #TODO: handle olefile errors, when an OLE file is malformed
  2737 + if self.detect_vba_macros():
  2738 + # print a waiting message only if the output is not redirected to a file:
  2739 + if sys.stdout.isatty():
  2740 + print 'Analysis...\r',
  2741 + sys.stdout.flush()
  2742 + self.analyze_macros(show_decoded_strings=show_decoded_strings,
  2743 + deobfuscate=deobfuscate)
  2744 + flags = TYPE2TAG[self.type]
  2745 + macros = autoexec = suspicious = iocs = hexstrings = base64obf = dridex = vba_obf = '-'
  2746 + if self.contains_macros: macros = 'M'
  2747 + if self.nb_autoexec: autoexec = 'A'
  2748 + if self.nb_suspicious: suspicious = 'S'
  2749 + if self.nb_iocs: iocs = 'I'
  2750 + if self.nb_hexstrings: hexstrings = 'H'
  2751 + if self.nb_base64strings: base64obf = 'B'
  2752 + if self.nb_dridexstrings: dridex = 'D'
  2753 + if self.nb_vbastrings: vba_obf = 'V'
  2754 + flags += '%s%s%s%s%s%s%s%s' % (macros, autoexec, suspicious, iocs, hexstrings,
  2755 + base64obf, dridex, vba_obf)
  2756 +
  2757 + line = '%-12s %s' % (flags, self.filename)
  2758 + print line
  2759 +
  2760 + # old table display:
  2761 + # macros = autoexec = suspicious = iocs = hexstrings = 'no'
  2762 + # if nb_macros: macros = 'YES:%d' % nb_macros
  2763 + # if nb_autoexec: autoexec = 'YES:%d' % nb_autoexec
  2764 + # if nb_suspicious: suspicious = 'YES:%d' % nb_suspicious
  2765 + # if nb_iocs: iocs = 'YES:%d' % nb_iocs
  2766 + # if nb_hexstrings: hexstrings = 'YES:%d' % nb_hexstrings
  2767 + # # 2nd line = info
  2768 + # print '%-8s %-7s %-7s %-7s %-7s %-7s' % (self.type, macros, autoexec, suspicious, iocs, hexstrings)
  2769 + except Exception as exc:
  2770 + # display the exception with full stack trace for debugging only
  2771 + log.debug('Error processing file %s (%s)' % (self.filename, exc),
  2772 + exc_info=True)
  2773 + raise ProcessingError(self.filename, exc)
  2774 +
2776 2775  
2777 2776 # t = prettytable.PrettyTable(('filename', 'type', 'macros', 'autoexec', 'suspicious', 'ioc', 'hexstrings'),
2778 2777 # header=False, border=False)
... ... @@ -2888,39 +2887,53 @@ def main():
2888 2887 # ignore directory names stored in zip files:
2889 2888 if container and filename.endswith('/'):
2890 2889 continue
2891   - # Open the file
  2890 +
2892 2891 try:
  2892 + # Open the file
2893 2893 vba_parser = VBA_Parser_CLI(filename, data=data, container=container)
  2894 +
  2895 + if options.output_mode == 'detailed':
  2896 + # fully detailed output
  2897 + vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
  2898 + display_code=options.display_code,
  2899 + hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only,
  2900 + show_deobfuscated_code=options.show_deobfuscated_code,
  2901 + deobfuscate=options.deobfuscate)
  2902 + elif options.output_mode in ('triage', 'unspecified'):
  2903 + # print container name when it changes:
  2904 + if container != previous_container:
  2905 + if container is not None:
  2906 + print '\nFiles in %s:' % container
  2907 + previous_container = container
  2908 + # summarized output for triage:
  2909 + vba_parser.process_file_triage(show_decoded_strings=options.show_decoded_strings,
  2910 + deobfuscate=options.deobfuscate)
  2911 + elif options.output_mode == 'json':
  2912 + json_results.append(
  2913 + vba_parser.process_file_json(show_decoded_strings=options.show_decoded_strings,
  2914 + display_code=options.display_code,
  2915 + hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only,
  2916 + show_deobfuscated_code=options.show_deobfuscated_code))
  2917 + else: # (should be impossible)
  2918 + raise ValueError('unexpected output mode: "{0}"!'.format(options.output_mode))
  2919 + count += 1
  2920 +
2894 2921 except FileOpenError as exc:
2895   - log.exception('Failed to open %s (%s)!' % (filename, exc))
  2922 + if options.output_mode in ('triage', 'unspecified'):
  2923 + print '%-12s %s - File format not supported' % ('?', filename)
  2924 + else:
  2925 + log.exception('Failed to open %s -- probably not supported!' % filename)
2896 2926 return_code = max(return_code, RETURN_OPEN_ERROR)
2897   - continue
  2927 + except ProcessingError as exc:
  2928 + if options.output_mode in ('triage', 'unspecified'):
  2929 + print '%-12s %s - %s' % ('!ERROR', filename, exc.orig_exception)
  2930 + else:
  2931 + log.exception('Error processing file %s (%s)!'
  2932 + % (filename, exc.orig_exception))
  2933 + return_code = max(return_code, RETURN_PARSE_ERROR)
  2934 + finally:
  2935 + vba_parser.close()
2898 2936  
2899   - if options.output_mode == 'detailed':
2900   - # fully detailed output
2901   - vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
2902   - display_code=options.display_code,
2903   - hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only,
2904   - show_deobfuscated_code=options.show_deobfuscated_code,
2905   - deobfuscate=options.deobfuscate)
2906   - elif options.output_mode in ('triage', 'unspecified'):
2907   - # print container name when it changes:
2908   - if container != previous_container:
2909   - if container is not None:
2910   - print '\nFiles in %s:' % container
2911   - previous_container = container
2912   - # summarized output for triage:
2913   - vba_parser.process_file_triage(show_decoded_strings=options.show_decoded_strings,
2914   - deobfuscate=options.deobfuscate)
2915   - elif options.output_mode == 'json':
2916   - json_results.append(
2917   - vba_parser.process_file_json(show_decoded_strings=options.show_decoded_strings,
2918   - display_code=options.display_code,
2919   - hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only,
2920   - show_deobfuscated_code=options.show_deobfuscated_code))
2921   - else: # (should be impossible)
2922   - raise ValueError('unexpected output mode: "{0}"!'.format(options.output_mode))
2923   - count += 1
2924 2937 if options.output_mode == 'triage':
2925 2938 print '\n(Flags: OpX=OpenXML, XML=Word2003XML, MHT=MHTML, TXT=Text, M=Macros, ' \
2926 2939 'A=Auto-executable, S=Suspicious keywords, I=IOCs, H=Hex strings, ' \
... ...