Commit e6d5614b555b4cd1cfff256f7629ecc5074d3744

Authored by Philippe Lagadec
1 parent e6148632

olevba: moved main functions to a class VBA_Parser_CLI, fixed issue when analysis was done twice

Showing 1 changed file with 209 additions and 180 deletions
oletools/olevba.py
@@ -146,6 +146,8 @@ https://github.com/unixfreak0037/officeparser @@ -146,6 +146,8 @@ https://github.com/unixfreak0037/officeparser
146 # 2015-07-12 PL: - added Hex function decoding to VBA Parser 146 # 2015-07-12 PL: - added Hex function decoding to VBA Parser
147 # 2015-07-13 PL: - added Base64 function decoding to VBA Parser 147 # 2015-07-13 PL: - added Base64 function decoding to VBA Parser
148 # 2015-09-06 PL: - improved VBA_Parser, refactored the main functions 148 # 2015-09-06 PL: - improved VBA_Parser, refactored the main functions
  149 +# 2015-09-13 PL: - moved main functions to a class VBA_Parser_CLI
  150 +# - fixed issue when analysis was done twice
149 151
150 __version__ = '0.33' 152 __version__ = '0.33'
151 153
@@ -234,6 +236,15 @@ TYPE_OpenXML = 'OpenXML' @@ -234,6 +236,15 @@ TYPE_OpenXML = 'OpenXML'
234 TYPE_Word2003_XML = 'Word2003_XML' 236 TYPE_Word2003_XML = 'Word2003_XML'
235 TYPE_MHTML = 'MHTML' 237 TYPE_MHTML = 'MHTML'
236 238
  239 +# short tag to display file types in triage mode:
  240 +TYPE2TAG = {
  241 + TYPE_OLE: 'OLE:',
  242 + TYPE_OpenXML: 'OpX:',
  243 + TYPE_Word2003_XML: 'XML:',
  244 + TYPE_MHTML: 'MHT:',
  245 +}
  246 +
  247 +
237 # MSO files ActiveMime header magic 248 # MSO files ActiveMime header magic
238 MSO_ACTIVEMIME_HEADER = 'ActiveMime' 249 MSO_ACTIVEMIME_HEADER = 'ActiveMime'
239 250
@@ -1619,7 +1630,7 @@ class VBA_Parser(object): @@ -1619,7 +1630,7 @@ class VBA_Parser(object):
1619 - PowerPoint 2007+ (.pptm, .ppsm) 1630 - PowerPoint 2007+ (.pptm, .ppsm)
1620 """ 1631 """
1621 1632
1622 - def __init__(self, filename, data=None): 1633 + def __init__(self, filename, data=None, container=None):
1623 """ 1634 """
1624 Constructor for VBA_Parser 1635 Constructor for VBA_Parser
1625 1636
@@ -1628,6 +1639,9 @@ class VBA_Parser(object): @@ -1628,6 +1639,9 @@ class VBA_Parser(object):
1628 :param data: None or bytes str, if None the file will be read from disk (or from the file-like object). 1639 :param data: None or bytes str, if None the file will be read from disk (or from the file-like object).
1629 If data is provided as a bytes string, it will be parsed as the content of the file in memory, 1640 If data is provided as a bytes string, it will be parsed as the content of the file in memory,
1630 and not read from disk. Note: files must be read in binary mode, i.e. open(f, 'rb'). 1641 and not read from disk. Note: files must be read in binary mode, i.e. open(f, 'rb').
  1642 +
  1643 + :param container: str, path and filename of container if the file is within
  1644 + a zip archive, None otherwise.
1631 """ 1645 """
1632 #TODO: filename should only be a string, data should be used for the file-like object 1646 #TODO: filename should only be a string, data should be used for the file-like object
1633 #TODO: filename should be mandatory, optional data is a string or file-like object 1647 #TODO: filename should be mandatory, optional data is a string or file-like object
@@ -1642,6 +1656,7 @@ class VBA_Parser(object): @@ -1642,6 +1656,7 @@ class VBA_Parser(object):
1642 self.ole_file = None 1656 self.ole_file = None
1643 self.ole_subfiles = [] 1657 self.ole_subfiles = []
1644 self.filename = filename 1658 self.filename = filename
  1659 + self.container = container
1645 self.type = None 1660 self.type = None
1646 self.vba_projects = None 1661 self.vba_projects = None
1647 self.contains_macros = None # will be set to True or False by detect_macros 1662 self.contains_macros = None # will be set to True or False by detect_macros
@@ -1951,6 +1966,9 @@ class VBA_Parser(object): @@ -1951,6 +1966,9 @@ class VBA_Parser(object):
1951 found in the file. 1966 found in the file.
1952 """ 1967 """
1953 if self.detect_vba_macros(): 1968 if self.detect_vba_macros():
  1969 + # if the analysis was already done, avoid doing it twice:
  1970 + if self.analysis_results is not None:
  1971 + return self.analysis_results
1954 # variable to merge source code from all modules: 1972 # variable to merge source code from all modules:
1955 if self.vba_code_all_modules is None: 1973 if self.vba_code_all_modules is None:
1956 self.vba_code_all_modules = '' 1974 self.vba_code_all_modules = ''
@@ -1987,187 +2005,197 @@ class VBA_Parser(object): @@ -1987,187 +2005,197 @@ class VBA_Parser(object):
1987 self.ole_file.close() 2005 self.ole_file.close()
1988 2006
1989 2007
1990 -def print_analysis(vba_parser, show_decoded_strings=False):  
1991 - """  
1992 - Analyze the provided VBA code, and print the results in a table  
1993 2008
1994 - :param vba_code: str, VBA source code to be analyzed  
1995 - :param show_decoded_strings: bool, if True hex-encoded strings will be displayed with their decoded content.  
1996 - :return: None 2009 +class VBA_Parser_CLI(VBA_Parser):
1997 """ 2010 """
1998 - # print a waiting message only if the output is not redirected to a file:  
1999 - if sys.stdout.isatty():  
2000 - print 'Analysis...\r',  
2001 - sys.stdout.flush()  
2002 - results = vba_parser.analyze_macros(show_decoded_strings)  
2003 - if results:  
2004 - t = prettytable.PrettyTable(('Type', 'Keyword', 'Description'))  
2005 - t.align = 'l'  
2006 - t.max_width['Type'] = 10  
2007 - t.max_width['Keyword'] = 20  
2008 - t.max_width['Description'] = 39  
2009 - for kw_type, keyword, description in results:  
2010 - # handle non printable strings:  
2011 - if not is_printable(keyword):  
2012 - keyword = repr(keyword)  
2013 - if not is_printable(description):  
2014 - description = repr(description)  
2015 - t.add_row((kw_type, keyword, description))  
2016 - print t  
2017 - else:  
2018 - print 'No suspicious keyword or IOC found.' 2011 + VBA parser and analyzer, adding methods for the command line interface
  2012 + of olevba. (see VBA_Parser)
  2013 + """
  2014 +
  2015 + def __init__(self, filename, data=None, container=None):
  2016 + """
  2017 + Constructor for VBA_Parser_CLI.
  2018 + Calls __init__ from VBA_Parser, but handles the TypeError exception
  2019 + when the file type is not supported.
2019 2020
  2021 + :param filename: filename or path of file to parse, or file-like object
2020 2022
2021 -def process_file(container, filename, data, show_decoded_strings=False,  
2022 - display_code=True, global_analysis=True, hide_attributes=True,  
2023 - vba_code_only=False):  
2024 - """  
2025 - Process a single file  
2026 -  
2027 - :param container: str, path and filename of container if the file is within  
2028 - a zip archive, None otherwise.  
2029 - :param filename: str, path and filename of file on disk, or within the container.  
2030 - :param data: bytes, content of the file if it is in a container, None if it is a file on disk.  
2031 - :param show_decoded_strings: bool, if True hex-encoded strings will be displayed with their decoded content.  
2032 - :param display_code: bool, if False VBA source code is not displayed (default True)  
2033 - :param global_analysis: bool, if True all modules are merged for a single analysis (default),  
2034 - otherwise each module is analyzed separately (old behaviour)  
2035 - :param hide_attributes: bool, if True the first lines starting with "Attribute VB" are hidden (default)  
2036 - """  
2037 - #TODO: replace print by writing to a provided output file (sys.stdout by default)  
2038 - # fix conflicting parameters:  
2039 - if vba_code_only and not display_code:  
2040 - display_code = True  
2041 - if container:  
2042 - display_filename = '%s in %s' % (filename, container)  
2043 - else:  
2044 - display_filename = filename  
2045 - print '=' * 79  
2046 - print 'FILE:', display_filename  
2047 - try:  
2048 - #TODO: handle olefile errors, when an OLE file is malformed  
2049 - vba = VBA_Parser(filename, data)  
2050 - print 'Type:', vba.type  
2051 - if vba.detect_vba_macros():  
2052 - #print 'Contains VBA Macros:'  
2053 - for (subfilename, stream_path, vba_filename, vba_code) in vba.extract_all_macros():  
2054 - if hide_attributes:  
2055 - # hide attribute lines:  
2056 - vba_code_filtered = filter_vba(vba_code)  
2057 - else:  
2058 - vba_code_filtered = vba_code  
2059 - print '-' * 79  
2060 - print 'VBA MACRO %s ' % vba_filename  
2061 - print 'in file: %s - OLE stream: %s' % (subfilename, repr(stream_path))  
2062 - if display_code:  
2063 - print '- ' * 39  
2064 - # detect empty macros:  
2065 - if vba_code_filtered.strip() == '':  
2066 - print '(empty macro)'  
2067 - else:  
2068 - print vba_code_filtered  
2069 - if not global_analysis and not vba_code_only:  
2070 - #TODO: remove this option  
2071 - raise NotImplementedError  
2072 - print '- ' * 39  
2073 - print 'ANALYSIS:'  
2074 - # analyse each module's code, filtered to avoid false positives:  
2075 - print_analysis(vba, show_decoded_strings)  
2076 - if global_analysis and not vba_code_only:  
2077 - # analyse the code from all modules at once:  
2078 - print_analysis(vba, show_decoded_strings) 2023 + :param data: None or bytes str, if None the file will be read from disk (or from the file-like object).
  2024 + If data is provided as a bytes string, it will be parsed as the content of the file in memory,
  2025 + and not read from disk. Note: files must be read in binary mode, i.e. open(f, 'rb').
  2026 +
  2027 + :param container: str, path and filename of container if the file is within
  2028 + a zip archive, None otherwise.
  2029 + """
  2030 + try:
  2031 + VBA_Parser.__init__(self, filename, data=data, container=container)
  2032 + except TypeError:
  2033 + # in that case, self.type=None
  2034 + pass
  2035 +
  2036 +
  2037 + def print_analysis(self, show_decoded_strings=False):
  2038 + """
  2039 + Analyze the provided VBA code, and print the results in a table
  2040 +
  2041 + :param vba_code: str, VBA source code to be analyzed
  2042 + :param show_decoded_strings: bool, if True hex-encoded strings will be displayed with their decoded content.
  2043 + :return: None
  2044 + """
  2045 + # print a waiting message only if the output is not redirected to a file:
  2046 + if sys.stdout.isatty():
  2047 + print 'Analysis...\r',
  2048 + sys.stdout.flush()
  2049 + results = self.analyze_macros(show_decoded_strings)
  2050 + if results:
  2051 + t = prettytable.PrettyTable(('Type', 'Keyword', 'Description'))
  2052 + t.align = 'l'
  2053 + t.max_width['Type'] = 10
  2054 + t.max_width['Keyword'] = 20
  2055 + t.max_width['Description'] = 39
  2056 + for kw_type, keyword, description in results:
  2057 + # handle non printable strings:
  2058 + if not is_printable(keyword):
  2059 + keyword = repr(keyword)
  2060 + if not is_printable(description):
  2061 + description = repr(description)
  2062 + t.add_row((kw_type, keyword, description))
  2063 + print t
2079 else: 2064 else:
2080 - print 'No VBA macros found.'  
2081 - except: #TypeError:  
2082 - #raise  
2083 - #TODO: print more info if debug mode  
2084 - #print sys.exc_value  
2085 - # display the exception with full stack trace for debugging, but do not stop:  
2086 - traceback.print_exc()  
2087 - print '' 2065 + print 'No suspicious keyword or IOC found.'
2088 2066
2089 -# short tag to display file types in triage mode:  
2090 -TYPE2TAG = {  
2091 - TYPE_OLE: 'OLE:',  
2092 - TYPE_OpenXML: 'OpX:',  
2093 - TYPE_Word2003_XML: 'XML:',  
2094 - TYPE_MHTML: 'MHT:',  
2095 -}  
2096 2067
2097 -def process_file_triage(container, filename, data):  
2098 - """  
2099 - Process a single file 2068 + def process_file(self, show_decoded_strings=False,
  2069 + display_code=True, global_analysis=True, hide_attributes=True,
  2070 + vba_code_only=False):
  2071 + """
  2072 + Process a single file
  2073 +
  2074 + :param filename: str, path and filename of file on disk, or within the container.
  2075 + :param data: bytes, content of the file if it is in a container, None if it is a file on disk.
  2076 + :param show_decoded_strings: bool, if True hex-encoded strings will be displayed with their decoded content.
  2077 + :param display_code: bool, if False VBA source code is not displayed (default True)
  2078 + :param global_analysis: bool, if True all modules are merged for a single analysis (default),
  2079 + otherwise each module is analyzed separately (old behaviour)
  2080 + :param hide_attributes: bool, if True the first lines starting with "Attribute VB" are hidden (default)
  2081 + """
  2082 + #TODO: replace print by writing to a provided output file (sys.stdout by default)
  2083 + # fix conflicting parameters:
  2084 + if vba_code_only and not display_code:
  2085 + display_code = True
  2086 + if self.container:
  2087 + display_filename = '%s in %s' % (self.filename, self.container)
  2088 + else:
  2089 + display_filename = self.filename
  2090 + print '=' * 79
  2091 + print 'FILE:', display_filename
  2092 + try:
  2093 + #TODO: handle olefile errors, when an OLE file is malformed
  2094 + print 'Type:', self.type
  2095 + if self.detect_vba_macros():
  2096 + #print 'Contains VBA Macros:'
  2097 + for (subfilename, stream_path, vba_filename, vba_code) in self.extract_all_macros():
  2098 + if hide_attributes:
  2099 + # hide attribute lines:
  2100 + vba_code_filtered = filter_vba(vba_code)
  2101 + else:
  2102 + vba_code_filtered = vba_code
  2103 + print '-' * 79
  2104 + print 'VBA MACRO %s ' % vba_filename
  2105 + print 'in file: %s - OLE stream: %s' % (subfilename, repr(stream_path))
  2106 + if display_code:
  2107 + print '- ' * 39
  2108 + # detect empty macros:
  2109 + if vba_code_filtered.strip() == '':
  2110 + print '(empty macro)'
  2111 + else:
  2112 + print vba_code_filtered
  2113 + if not global_analysis and not vba_code_only:
  2114 + #TODO: remove this option
  2115 + raise NotImplementedError
  2116 + print '- ' * 39
  2117 + print 'ANALYSIS:'
  2118 + # analyse each module's code, filtered to avoid false positives:
  2119 + self.print_analysis(show_decoded_strings)
  2120 + if global_analysis and not vba_code_only:
  2121 + # analyse the code from all modules at once:
  2122 + self.print_analysis(show_decoded_strings)
  2123 + else:
  2124 + print 'No VBA macros found.'
  2125 + except: #TypeError:
  2126 + #raise
  2127 + #TODO: print more info if debug mode
  2128 + #print sys.exc_value
  2129 + # display the exception with full stack trace for debugging, but do not stop:
  2130 + traceback.print_exc()
  2131 + print ''
2100 2132
2101 - :param container: str, path and filename of container if the file is within  
2102 - a zip archive, None otherwise.  
2103 - :param filename: str, path and filename of file on disk, or within the container.  
2104 - :param data: bytes, content of the file if it is in a container, None if it is a file on disk.  
2105 - """  
2106 - #TODO: replace print by writing to a provided output file (sys.stdout by default)  
2107 - # ftype = 'Other'  
2108 - message = ''  
2109 - try:  
2110 - #TODO: handle olefile errors, when an OLE file is malformed  
2111 - vba = VBA_Parser(filename, data)  
2112 - if vba.detect_vba_macros():  
2113 - # print a waiting message only if the output is not redirected to a file:  
2114 - if sys.stdout.isatty():  
2115 - print 'Analysis...\r',  
2116 - sys.stdout.flush()  
2117 - vba.analyze_macros()  
2118 - flags = TYPE2TAG[vba.type]  
2119 - macros = autoexec = suspicious = iocs = hexstrings = base64obf = dridex = vba_obf = '-'  
2120 - if vba.nb_macros: macros = 'M'  
2121 - if vba.nb_autoexec: autoexec = 'A'  
2122 - if vba.nb_suspicious: suspicious = 'S'  
2123 - if vba.nb_iocs: iocs = 'I'  
2124 - if vba.nb_hexstrings: hexstrings = 'H'  
2125 - if vba.nb_base64strings: base64obf = 'B'  
2126 - if vba.nb_dridexstrings: dridex = 'D'  
2127 - if vba.nb_vbastrings: vba_obf = 'V'  
2128 - flags += '%s%s%s%s%s%s%s%s' % (macros, autoexec, suspicious, iocs, hexstrings,  
2129 - base64obf, dridex, vba_obf)  
2130 - # old table display:  
2131 - # macros = autoexec = suspicious = iocs = hexstrings = 'no'  
2132 - # if nb_macros: macros = 'YES:%d' % nb_macros  
2133 - # if nb_autoexec: autoexec = 'YES:%d' % nb_autoexec  
2134 - # if nb_suspicious: suspicious = 'YES:%d' % nb_suspicious  
2135 - # if nb_iocs: iocs = 'YES:%d' % nb_iocs  
2136 - # if nb_hexstrings: hexstrings = 'YES:%d' % nb_hexstrings  
2137 - # # 2nd line = info  
2138 - # print '%-8s %-7s %-7s %-7s %-7s %-7s' % (vba.type, macros, autoexec, suspicious, iocs, hexstrings)  
2139 - except TypeError:  
2140 - # file type not OLE nor OpenXML  
2141 - flags = '?'  
2142 - message = 'File format not supported'  
2143 - except:  
2144 - # another error occurred  
2145 - #raise  
2146 - #TODO: print more info if debug mode  
2147 - #TODO: distinguish real errors from incorrect file types  
2148 - flags = '!ERROR'  
2149 - message = sys.exc_value  
2150 - line = '%-12s %s' % (flags, filename)  
2151 - if message:  
2152 - line += ' - %s' % message  
2153 - print line  
2154 -  
2155 - # t = prettytable.PrettyTable(('filename', 'type', 'macros', 'autoexec', 'suspicious', 'ioc', 'hexstrings'),  
2156 - # header=False, border=False)  
2157 - # t.align = 'l'  
2158 - # t.max_width['filename'] = 30  
2159 - # t.max_width['type'] = 10  
2160 - # t.max_width['macros'] = 6  
2161 - # t.max_width['autoexec'] = 6  
2162 - # t.max_width['suspicious'] = 6  
2163 - # t.max_width['ioc'] = 6  
2164 - # t.max_width['hexstrings'] = 6  
2165 - # t.add_row((filename, ftype, macros, autoexec, suspicious, iocs, hexstrings))  
2166 - # print t  
2167 -  
2168 -  
2169 -def main_triage_quick():  
2170 - pass 2133 +
  2134 + def process_file_triage(self):
  2135 + """
  2136 + Process a file in triage mode, showing only summary results on one line.
  2137 + """
  2138 + #TODO: replace print by writing to a provided output file (sys.stdout by default)
  2139 + message = ''
  2140 + try:
  2141 + if self.type is not None:
  2142 + #TODO: handle olefile errors, when an OLE file is malformed
  2143 + if self.detect_vba_macros():
  2144 + # print a waiting message only if the output is not redirected to a file:
  2145 + if sys.stdout.isatty():
  2146 + print 'Analysis...\r',
  2147 + sys.stdout.flush()
  2148 + self.analyze_macros()
  2149 + flags = TYPE2TAG[self.type]
  2150 + macros = autoexec = suspicious = iocs = hexstrings = base64obf = dridex = vba_obf = '-'
  2151 + if self.nb_macros: macros = 'M'
  2152 + if self.nb_autoexec: autoexec = 'A'
  2153 + if self.nb_suspicious: suspicious = 'S'
  2154 + if self.nb_iocs: iocs = 'I'
  2155 + if self.nb_hexstrings: hexstrings = 'H'
  2156 + if self.nb_base64strings: base64obf = 'B'
  2157 + if self.nb_dridexstrings: dridex = 'D'
  2158 + if self.nb_vbastrings: vba_obf = 'V'
  2159 + flags += '%s%s%s%s%s%s%s%s' % (macros, autoexec, suspicious, iocs, hexstrings,
  2160 + base64obf, dridex, vba_obf)
  2161 + # old table display:
  2162 + # macros = autoexec = suspicious = iocs = hexstrings = 'no'
  2163 + # if nb_macros: macros = 'YES:%d' % nb_macros
  2164 + # if nb_autoexec: autoexec = 'YES:%d' % nb_autoexec
  2165 + # if nb_suspicious: suspicious = 'YES:%d' % nb_suspicious
  2166 + # if nb_iocs: iocs = 'YES:%d' % nb_iocs
  2167 + # if nb_hexstrings: hexstrings = 'YES:%d' % nb_hexstrings
  2168 + # # 2nd line = info
  2169 + # print '%-8s %-7s %-7s %-7s %-7s %-7s' % (self.type, macros, autoexec, suspicious, iocs, hexstrings)
  2170 + else:
  2171 + # self.type==None
  2172 + # file type not OLE nor OpenXML
  2173 + flags = '?'
  2174 + message = 'File format not supported'
  2175 + except:
  2176 + # another error occurred
  2177 + #raise
  2178 + #TODO: print more info if debug mode
  2179 + #TODO: distinguish real errors from incorrect file types
  2180 + flags = '!ERROR'
  2181 + message = sys.exc_value
  2182 + line = '%-12s %s' % (flags, self.filename)
  2183 + if message:
  2184 + line += ' - %s' % message
  2185 + print line
  2186 +
  2187 + # t = prettytable.PrettyTable(('filename', 'type', 'macros', 'autoexec', 'suspicious', 'ioc', 'hexstrings'),
  2188 + # header=False, border=False)
  2189 + # t.align = 'l'
  2190 + # t.max_width['filename'] = 30
  2191 + # t.max_width['type'] = 10
  2192 + # t.max_width['macros'] = 6
  2193 + # t.max_width['autoexec'] = 6
  2194 + # t.max_width['suspicious'] = 6
  2195 + # t.max_width['ioc'] = 6
  2196 + # t.max_width['hexstrings'] = 6
  2197 + # t.add_row((filename, ftype, macros, autoexec, suspicious, iocs, hexstrings))
  2198 + # print t
2171 2199
2172 2200
2173 #=== MAIN ===================================================================== 2201 #=== MAIN =====================================================================
@@ -2244,14 +2272,17 @@ def main(): @@ -2244,14 +2272,17 @@ def main():
2244 previous_container = None 2272 previous_container = None
2245 count = 0 2273 count = 0
2246 container = filename = data = None 2274 container = filename = data = None
  2275 + vba_parser = None
2247 for container, filename, data in xglob.iter_files(args, recursive=options.recursive, 2276 for container, filename, data in xglob.iter_files(args, recursive=options.recursive,
2248 zip_password=options.zip_password, zip_fname=options.zip_fname): 2277 zip_password=options.zip_password, zip_fname=options.zip_fname):
2249 # ignore directory names stored in zip files: 2278 # ignore directory names stored in zip files:
2250 if container and filename.endswith('/'): 2279 if container and filename.endswith('/'):
2251 continue 2280 continue
  2281 + # Open the file
  2282 + vba_parser = VBA_Parser_CLI(filename, data=data, container=container)
2252 if options.detailed_mode and not options.triage_mode: 2283 if options.detailed_mode and not options.triage_mode:
2253 # fully detailed output 2284 # fully detailed output
2254 - process_file(container, filename, data, show_decoded_strings=options.show_decoded_strings, 2285 + vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
2255 display_code=options.display_code, global_analysis=options.global_analysis, 2286 display_code=options.display_code, global_analysis=options.global_analysis,
2256 hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only) 2287 hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only)
2257 else: 2288 else:
@@ -2261,7 +2292,7 @@ def main(): @@ -2261,7 +2292,7 @@ def main():
2261 print '\nFiles in %s:' % container 2292 print '\nFiles in %s:' % container
2262 previous_container = container 2293 previous_container = container
2263 # summarized output for triage: 2294 # summarized output for triage:
2264 - process_file_triage(container, filename, data) 2295 + vba_parser.process_file_triage()
2265 count += 1 2296 count += 1
2266 if not options.detailed_mode or options.triage_mode: 2297 if not options.detailed_mode or options.triage_mode:
2267 print '\n(Flags: OpX=OpenXML, XML=Word2003XML, MHT=MHTML, M=Macros, ' \ 2298 print '\n(Flags: OpX=OpenXML, XML=Word2003XML, MHT=MHTML, M=Macros, ' \
@@ -2270,9 +2301,7 @@ def main(): @@ -2270,9 +2301,7 @@ def main():
2270 2301
2271 if count == 1 and not options.triage_mode and not options.detailed_mode: 2302 if count == 1 and not options.triage_mode and not options.detailed_mode:
2272 # if options -t and -d were not specified and it's a single file, print details: 2303 # if options -t and -d were not specified and it's a single file, print details:
2273 - #TODO: avoid doing the analysis twice by storing results  
2274 - #TODO: all the cli functions should be methods of a class VBA_Parser_CLI  
2275 - process_file(container, filename, data, show_decoded_strings=options.show_decoded_strings, 2304 + vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
2276 display_code=options.display_code, global_analysis=options.global_analysis, 2305 display_code=options.display_code, global_analysis=options.global_analysis,
2277 hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only) 2306 hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only)
2278 2307
@@ -2280,4 +2309,4 @@ def main(): @@ -2280,4 +2309,4 @@ def main():
2280 if __name__ == '__main__': 2309 if __name__ == '__main__':
2281 main() 2310 main()
2282 2311
2283 - # This was coded while listening to "Dust" from I Love You But I've Chosen Darkness  
2284 \ No newline at end of file 2312 \ No newline at end of file
  2313 +# This was coded while listening to "Dust" from I Love You But I've Chosen Darkness
2285 \ No newline at end of file 2314 \ No newline at end of file