diff --git a/.gitignore b/.gitignore index 174bad8..e52902f 100644 --- a/.gitignore +++ b/.gitignore @@ -98,3 +98,4 @@ ENV/ .ropeproject /temp/ +/issues/ diff --git a/LICENSE.md b/LICENSE.md index 051431c..1cb968f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ This license applies to the python-oletools package, apart from the thirdparty folder which contains third-party files published with their own license. -The python-oletools package is copyright (c) 2012-2023 Philippe Lagadec (http://www.decalage.info) +The python-oletools package is copyright (c) 2012-2024 Philippe Lagadec (http://www.decalage.info) All rights reserved. diff --git a/README.md b/README.md index 6fb484a..66dba96 100644 --- a/README.md +++ b/README.md @@ -145,8 +145,10 @@ Projects using oletools: oletools are used by a number of projects and online malware analysis services, including [ACE](https://github.com/IntegralDefense/ACE), +[ADAPT](https://www.blackhat.com/eu-23/briefings/schedule/index.html#unmasking-apts-an-automated-approach-for-real-world-threat-attribution-35162), [Anlyz.io](https://sandbox.anlyz.io/), [AssemblyLine](https://www.cse-cst.gc.ca/en/assemblyline), +[Binary Refinery](https://github.com/binref/refinery), [CAPE](https://github.com/ctxis/CAPE), [CinCan](https://cincan.io), [Cortex XSOAR (Palo Alto)](https://cortex.marketplace.pan.dev/marketplace/details/Oletools/), @@ -156,6 +158,7 @@ including [DIARIO](https://diario.elevenpaths.com/), [dridex.malwareconfig.com](https://dridex.malwareconfig.com), [EML Analyzer](https://github.com/ninoseki/eml_analyzer), +[EXPMON](https://pub.expmon.com/), [FAME](https://certsocietegenerale.github.io/fame/), [FLARE-VM](https://github.com/fireeye/flare-vm), [GLIMPS Malware](https://www.glimps.fr/en/glimps-malware-2/), @@ -177,6 +180,7 @@ including [PyCIRCLean](https://github.com/CIRCL/PyCIRCLean), [QFlow](https://www.quarkslab.com/products-qflow/), [Qu1cksc0pe](https://github.com/CYB3RMX/Qu1cksc0pe), +[Tylabs QuickSand](https://github.com/tylabs/quicksand), [REMnux](https://remnux.org/), [Snake](https://github.com/countercept/snake), [SNDBOX](https://app.sndbox.com), @@ -252,7 +256,7 @@ License This license applies to the python-oletools package, apart from the thirdparty folder which contains third-party files published with their own license. -The python-oletools package is copyright (c) 2012-2023 Philippe Lagadec (http://www.decalage.info) +The python-oletools package is copyright (c) 2012-2024 Philippe Lagadec (http://www.decalage.info) All rights reserved. diff --git a/oletools/olevba.py b/oletools/olevba.py index 00f1eb9..4bb63f6 100644 --- a/oletools/olevba.py +++ b/oletools/olevba.py @@ -32,7 +32,7 @@ https://github.com/unixfreak0037/officeparser # === LICENSE ================================================================== -# olevba is copyright (c) 2014-2022 Philippe Lagadec (http://www.decalage.info) +# olevba is copyright (c) 2014-2024 Philippe Lagadec (http://www.decalage.info) # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -234,8 +234,9 @@ from __future__ import print_function # 2020-09-28 PL: - added VBA_Parser.get_vba_code_all_modules (partial fix # for issue #619) # 2021-04-14 PL: - added detection of Workbook_BeforeClose (issue #518) +# 2021-11-09 KJ: - added PROJECTCOMPATVERSION Record on dir Stream -__version__ = '0.60.2dev1' +__version__ = '0.60.2dev5' #------------------------------------------------------------------------------ # TODO: @@ -1701,9 +1702,25 @@ class VBA_Project(object): if self.syskind not in SYSKIND_NAME: log.error("invalid PROJECTSYSKIND_SysKind {0:04X}".format(self.syskind)) - # PROJECTLCID Record + # PROJECTLCID Record or PROJECTCOMPATVERSION Record + project_id = struct.unpack("=2.1.0,<3 +pyparsing>=2.1.0,<4 olefile>=0.46 easygui colorclass diff --git a/setup.py b/setup.py index 3ed5a8c..2cefe68 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ import os, fnmatch #--- METADATA ----------------------------------------------------------------- name = "oletools" -version = '0.60.2dev4' +version = '0.60.2dev5' desc = "Python tools to analyze security characteristics of MS Office and OLE files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), for Malware Analysis and Incident Response #DFIR" long_desc = open('oletools/README.rst').read() author = "Philippe Lagadec" @@ -320,7 +320,7 @@ def main(): test_suite="tests", # scripts=scripts, install_requires=[ - "pyparsing>=2.1.0,<3", # changed from 2.2.0 to 2.1.0 for issue #481 + "pyparsing>=2.1.0,<4", # changed from 2.2.0 to 2.1.0 for issue #481 "olefile>=0.46", "easygui", 'colorclass', diff --git a/tests/oleid/test_basic.py b/tests/oleid/test_basic.py index 3adefa6..ed031cf 100644 --- a/tests/oleid/test_basic.py +++ b/tests/oleid/test_basic.py @@ -67,6 +67,11 @@ class TestOleIDBasic(unittest.TestCase): '949: ANSI/OEM Korean (Unified Hangul Code)') self.assertEqual(value_dict['author'], b'\xb1\xe8\xb1\xe2\xc1\xa4;kijeong') + elif 'olevba/sample_with_vba.ppt' in filename: + self.assertEqual(value_dict['codepage'], + '949: ANSI/OEM Korean (Unified Hangul Code)') + self.assertEqual(value_dict['author'], + b'\xb1\xe8 \xb1\xe2\xc1\xa4') else: self.assertEqual(value_dict['codepage'], '1252: ANSI Latin 1; Western European (Windows)') diff --git a/tests/olevba/test_basic.py b/tests/olevba/test_basic.py index dd917d3..b9e70c0 100644 --- a/tests/olevba/test_basic.py +++ b/tests/olevba/test_basic.py @@ -151,6 +151,24 @@ class TestOlevbaBasic(unittest.TestCase): self.assertIn('AutoExec', types) self.assertIn('Suspicious', types) + def test_dir_stream_record_project_compat_version(self): + """Test PROJECTCOMPATVERSION record on dir stream with a ppt file.""" + input_file = join(DATA_BASE_DIR, 'olevba', 'sample_with_vba.ppt') + output, ret_code = call_and_capture('olevba', args=(input_file, "--loglevel", "debug")) + + # check return code + self.assertEqual(ret_code, 0) + + # not expected string: + self.assertNotIn('invalid value for PROJECTLCID_Id expected 0002 got', output) + self.assertNotIn('Error in _extract_vba', output) + + # compat version in debug mode: + self.assertIn('compat version: 2', output) + + # vba contents: + self.assertIn('Sub Action_Click()\n MsgBox "The action button clicked!"\nEnd Sub', output) + # just in case somebody calls this file as a script if __name__ == '__main__': diff --git a/tests/test-data/olevba/sample_with_vba.ppt b/tests/test-data/olevba/sample_with_vba.ppt new file mode 100644 index 0000000..5c560c1 --- /dev/null +++ b/tests/test-data/olevba/sample_with_vba.ppt