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