Commit c556697486817d399f1f5f825e23792f3eff24b1

Authored by Philippe Lagadec
1 parent 977cdd30

olevba: KeyboardInterrupt is now raised properly in every function

Showing 1 changed file with 53 additions and 1 deletions
oletools/olevba.py
@@ -160,13 +160,13 @@ https://github.com/unixfreak0037/officeparser @@ -160,13 +160,13 @@ https://github.com/unixfreak0037/officeparser
160 # - improved logging, added -l option 160 # - improved logging, added -l option
161 # 2016-01-31 PL: - fixed issue #31 in VBA_Parser.open_mht 161 # 2016-01-31 PL: - fixed issue #31 in VBA_Parser.open_mht
162 # - fixed issue #32 by monkeypatching email.feedparser 162 # - fixed issue #32 by monkeypatching email.feedparser
  163 +# 2016-02-07 PL: - KeyboardInterrupt is now raised properly
163 164
164 __version__ = '0.42' 165 __version__ = '0.42'
165 166
166 #------------------------------------------------------------------------------ 167 #------------------------------------------------------------------------------
167 # TODO: 168 # TODO:
168 # + option --fast to disable VBA expressions parsing 169 # + option --fast to disable VBA expressions parsing
169 -# + do not use logging, but a provided logger (null logger by default)  
170 # + setup logging (common with other oletools) 170 # + setup logging (common with other oletools)
171 # + add xor bruteforcing like bbharvest 171 # + add xor bruteforcing like bbharvest
172 # + options -a and -c should imply -d 172 # + options -a and -c should imply -d
@@ -187,6 +187,7 @@ __version__ = '0.42' @@ -187,6 +187,7 @@ __version__ = '0.42'
187 # - extract_macros: convert to a class, split long function into smaller methods 187 # - extract_macros: convert to a class, split long function into smaller methods
188 # - extract_macros: read bytes from stream file objects instead of strings 188 # - extract_macros: read bytes from stream file objects instead of strings
189 # - extract_macros: use combined struct.unpack instead of many calls 189 # - extract_macros: use combined struct.unpack instead of many calls
  190 +# - all except clauses should target specific exceptions
190 191
191 #------------------------------------------------------------------------------ 192 #------------------------------------------------------------------------------
192 # REFERENCES: 193 # REFERENCES:
@@ -778,6 +779,9 @@ def mso_file_extract(data): @@ -778,6 +779,9 @@ def mso_file_extract(data):
778 try: 779 try:
779 offset = struct.unpack_from('<H', data, offset=0x1E)[0] + 46 780 offset = struct.unpack_from('<H', data, offset=0x1E)[0] + 46
780 log.debug('Parsing MSO file: data offset = 0x%X' % offset) 781 log.debug('Parsing MSO file: data offset = 0x%X' % offset)
  782 + except KeyboardInterrupt:
  783 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  784 + raise
781 except: 785 except:
782 log.exception('Unable to parse MSO/ActiveMime file header') 786 log.exception('Unable to parse MSO/ActiveMime file header')
783 raise RuntimeError('Unable to parse MSO/ActiveMime file header') 787 raise RuntimeError('Unable to parse MSO/ActiveMime file header')
@@ -790,6 +794,9 @@ def mso_file_extract(data): @@ -790,6 +794,9 @@ def mso_file_extract(data):
790 log.debug('Attempting zlib decompression from MSO file offset 0x%X' % start) 794 log.debug('Attempting zlib decompression from MSO file offset 0x%X' % start)
791 extracted_data = zlib.decompress(data[start:]) 795 extracted_data = zlib.decompress(data[start:])
792 return extracted_data 796 return extracted_data
  797 + except KeyboardInterrupt:
  798 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  799 + raise
793 except: 800 except:
794 log.exception('zlib decompression failed') 801 log.exception('zlib decompression failed')
795 # None of the guessed offsets worked, let's try brute-forcing by looking 802 # None of the guessed offsets worked, let's try brute-forcing by looking
@@ -801,6 +808,9 @@ def mso_file_extract(data): @@ -801,6 +808,9 @@ def mso_file_extract(data):
801 log.debug('Attempting zlib decompression from MSO file offset 0x%X' % start) 808 log.debug('Attempting zlib decompression from MSO file offset 0x%X' % start)
802 extracted_data = zlib.decompress(data[start:]) 809 extracted_data = zlib.decompress(data[start:])
803 return extracted_data 810 return extracted_data
  811 + except KeyboardInterrupt:
  812 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  813 + raise
804 except: 814 except:
805 log.exception('zlib decompression failed') 815 log.exception('zlib decompression failed')
806 raise RuntimeError('Unable to decompress data from a MSO/ActiveMime file') 816 raise RuntimeError('Unable to decompress data from a MSO/ActiveMime file')
@@ -1506,6 +1516,9 @@ def detect_base64_strings(vba_code): @@ -1506,6 +1516,9 @@ def detect_base64_strings(vba_code):
1506 decoded = base64.b64decode(value) 1516 decoded = base64.b64decode(value)
1507 results.append((value, decoded)) 1517 results.append((value, decoded))
1508 found.add(value) 1518 found.add(value)
  1519 + except KeyboardInterrupt:
  1520 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1521 + raise
1509 except: 1522 except:
1510 # if an exception occurs, it is likely not a base64-encoded string 1523 # if an exception occurs, it is likely not a base64-encoded string
1511 pass 1524 pass
@@ -1533,6 +1546,9 @@ def detect_dridex_strings(vba_code): @@ -1533,6 +1546,9 @@ def detect_dridex_strings(vba_code):
1533 decoded = DridexUrlDecode(value) 1546 decoded = DridexUrlDecode(value)
1534 results.append((value, decoded)) 1547 results.append((value, decoded))
1535 found.add(value) 1548 found.add(value)
  1549 + except KeyboardInterrupt:
  1550 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1551 + raise
1536 except: 1552 except:
1537 # if an exception occurs, it is likely not a dridex-encoded string 1553 # if an exception occurs, it is likely not a dridex-encoded string
1538 pass 1554 pass
@@ -1858,6 +1874,9 @@ class VBA_Parser(object): @@ -1858,6 +1874,9 @@ class VBA_Parser(object):
1858 # TODO: raise TypeError if this is a Powerpoint 97 file, since VBA macros cannot be detected yet 1874 # TODO: raise TypeError if this is a Powerpoint 97 file, since VBA macros cannot be detected yet
1859 # set type only if parsing succeeds 1875 # set type only if parsing succeeds
1860 self.type = TYPE_OLE 1876 self.type = TYPE_OLE
  1877 + except KeyboardInterrupt:
  1878 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1879 + raise
1861 except: 1880 except:
1862 # TODO: handle OLE parsing exceptions 1881 # TODO: handle OLE parsing exceptions
1863 log.exception('Failed OLE parsing for file %r' % self.filename) 1882 log.exception('Failed OLE parsing for file %r' % self.filename)
@@ -1887,12 +1906,18 @@ class VBA_Parser(object): @@ -1887,12 +1906,18 @@ class VBA_Parser(object):
1887 ole_data = z.open(subfile).read() 1906 ole_data = z.open(subfile).read()
1888 try: 1907 try:
1889 self.ole_subfiles.append(VBA_Parser(filename=subfile, data=ole_data)) 1908 self.ole_subfiles.append(VBA_Parser(filename=subfile, data=ole_data))
  1909 + except KeyboardInterrupt:
  1910 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1911 + raise
1890 except: 1912 except:
1891 log.debug('%s is not a valid OLE file' % subfile) 1913 log.debug('%s is not a valid OLE file' % subfile)
1892 continue 1914 continue
1893 z.close() 1915 z.close()
1894 # set type only if parsing succeeds 1916 # set type only if parsing succeeds
1895 self.type = TYPE_OpenXML 1917 self.type = TYPE_OpenXML
  1918 + except KeyboardInterrupt:
  1919 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1920 + raise
1896 except: 1921 except:
1897 # TODO: handle parsing exceptions 1922 # TODO: handle parsing exceptions
1898 log.exception('Failed Zip/OpenXML parsing for file %r' % self.filename) 1923 log.exception('Failed Zip/OpenXML parsing for file %r' % self.filename)
@@ -1923,12 +1948,18 @@ class VBA_Parser(object): @@ -1923,12 +1948,18 @@ class VBA_Parser(object):
1923 ole_data = mso_file_extract(mso_data) 1948 ole_data = mso_file_extract(mso_data)
1924 try: 1949 try:
1925 self.ole_subfiles.append(VBA_Parser(filename=fname, data=ole_data)) 1950 self.ole_subfiles.append(VBA_Parser(filename=fname, data=ole_data))
  1951 + except KeyboardInterrupt:
  1952 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1953 + raise
1926 except: 1954 except:
1927 log.error('%s does not contain a valid OLE file' % fname) 1955 log.error('%s does not contain a valid OLE file' % fname)
1928 else: 1956 else:
1929 log.error('%s is not a valid MSO file' % fname) 1957 log.error('%s is not a valid MSO file' % fname)
1930 # set type only if parsing succeeds 1958 # set type only if parsing succeeds
1931 self.type = TYPE_Word2003_XML 1959 self.type = TYPE_Word2003_XML
  1960 + except KeyboardInterrupt:
  1961 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  1962 + raise
1932 except: 1963 except:
1933 # TODO: differentiate exceptions for each parsing stage 1964 # TODO: differentiate exceptions for each parsing stage
1934 log.exception('Failed XML parsing for file %r' % self.filename) 1965 log.exception('Failed XML parsing for file %r' % self.filename)
@@ -1979,8 +2010,14 @@ class VBA_Parser(object): @@ -1979,8 +2010,14 @@ class VBA_Parser(object):
1979 # TODO: check if it is actually an OLE file 2010 # TODO: check if it is actually an OLE file
1980 # TODO: get the MSO filename from content_location? 2011 # TODO: get the MSO filename from content_location?
1981 self.ole_subfiles.append(VBA_Parser(filename=fname, data=ole_data)) 2012 self.ole_subfiles.append(VBA_Parser(filename=fname, data=ole_data))
  2013 + except KeyboardInterrupt:
  2014 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2015 + raise
1982 except: 2016 except:
1983 log.debug('%s does not contain a valid OLE file' % fname) 2017 log.debug('%s does not contain a valid OLE file' % fname)
  2018 + except KeyboardInterrupt:
  2019 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2020 + raise
1984 except: 2021 except:
1985 log.exception('Failed decompressing an MSO container in %r - %s' 2022 log.exception('Failed decompressing an MSO container in %r - %s'
1986 % (fname, MSG_OLEVBA_ISSUES)) 2023 % (fname, MSG_OLEVBA_ISSUES))
@@ -1989,10 +2026,16 @@ class VBA_Parser(object): @@ -1989,10 +2026,16 @@ class VBA_Parser(object):
1989 try: 2026 try:
1990 log.debug('type(part_data) = %s' % type(part_data)) 2027 log.debug('type(part_data) = %s' % type(part_data))
1991 log.debug('part_data[0:20] = %r' % part_data[0:20]) 2028 log.debug('part_data[0:20] = %r' % part_data[0:20])
  2029 + except KeyboardInterrupt:
  2030 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2031 + raise
1992 except: 2032 except:
1993 pass 2033 pass
1994 # set type only if parsing succeeds 2034 # set type only if parsing succeeds
1995 self.type = TYPE_MHTML 2035 self.type = TYPE_MHTML
  2036 + except KeyboardInterrupt:
  2037 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2038 + raise
1996 except: 2039 except:
1997 log.exception('Failed MIME parsing for file %r - %s' 2040 log.exception('Failed MIME parsing for file %r - %s'
1998 % (self.filename, MSG_OLEVBA_ISSUES)) 2041 % (self.filename, MSG_OLEVBA_ISSUES))
@@ -2012,6 +2055,9 @@ class VBA_Parser(object): @@ -2012,6 +2055,9 @@ class VBA_Parser(object):
2012 self.contains_macros = True 2055 self.contains_macros = True
2013 # set type only if parsing succeeds 2056 # set type only if parsing succeeds
2014 self.type = TYPE_TEXT 2057 self.type = TYPE_TEXT
  2058 + except KeyboardInterrupt:
  2059 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2060 + raise
2015 except: 2061 except:
2016 log.exception('Failed text parsing for file %r - %s' 2062 log.exception('Failed text parsing for file %r - %s'
2017 % (self.filename, MSG_OLEVBA_ISSUES)) 2063 % (self.filename, MSG_OLEVBA_ISSUES))
@@ -2364,6 +2410,9 @@ class VBA_Parser_CLI(VBA_Parser): @@ -2364,6 +2410,9 @@ class VBA_Parser_CLI(VBA_Parser):
2364 print self.reveal() 2410 print self.reveal()
2365 else: 2411 else:
2366 print 'No VBA macros found.' 2412 print 'No VBA macros found.'
  2413 + except KeyboardInterrupt:
  2414 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2415 + raise
2367 except: #TypeError: 2416 except: #TypeError:
2368 #raise 2417 #raise
2369 #TODO: print more info if debug mode 2418 #TODO: print more info if debug mode
@@ -2414,6 +2463,9 @@ class VBA_Parser_CLI(VBA_Parser): @@ -2414,6 +2463,9 @@ class VBA_Parser_CLI(VBA_Parser):
2414 # file type not OLE nor OpenXML 2463 # file type not OLE nor OpenXML
2415 flags = '?' 2464 flags = '?'
2416 message = 'File format not supported' 2465 message = 'File format not supported'
  2466 + except KeyboardInterrupt:
  2467 + # do not ignore exceptions when the user presses Ctrl+C/Pause:
  2468 + raise
2417 except: 2469 except:
2418 # another error occurred 2470 # another error occurred
2419 #raise 2471 #raise