Commit f302bdeb762ddf49a809a639948ebfaadc37f418
1 parent
d5b971e4
olevba: added PROJECTCOMPATVERSION Record on dir Stream
Showing
3 changed files
with
37 additions
and
2 deletions
oletools/olevba.py
| ... | ... | @@ -234,6 +234,7 @@ from __future__ import print_function |
| 234 | 234 | # 2020-09-28 PL: - added VBA_Parser.get_vba_code_all_modules (partial fix |
| 235 | 235 | # for issue #619) |
| 236 | 236 | # 2021-04-14 PL: - added detection of Workbook_BeforeClose (issue #518) |
| 237 | +# 2021-11-09 KJ: - added PROJECTCOMPATVERSION Record on dir Stream | |
| 237 | 238 | |
| 238 | 239 | __version__ = '0.60.1.dev3' |
| 239 | 240 | |
| ... | ... | @@ -1720,9 +1721,25 @@ class VBA_Project(object): |
| 1720 | 1721 | if self.syskind not in SYSKIND_NAME: |
| 1721 | 1722 | log.error("invalid PROJECTSYSKIND_SysKind {0:04X}".format(self.syskind)) |
| 1722 | 1723 | |
| 1723 | - # PROJECTLCID Record | |
| 1724 | + # PROJECTLCID Record or PROJECTCOMPATVERSION Record | |
| 1725 | + project_id = struct.unpack("<H", dir_stream.read(2))[0] | |
| 1726 | + if project_id == 0x004A: | |
| 1727 | + # PROJECTCOMPATVERSION Record | |
| 1728 | + # Specifies the VBA project’s compat version. | |
| 1729 | + projectcompatversion_id = project_id | |
| 1730 | + self.check_value('PROJETCOMPATVERSION_Id', 0x004A, projectcompatversion_id) | |
| 1731 | + projectcompatversion_size = struct.unpack("<L", dir_stream.read(4))[0] | |
| 1732 | + self.check_value('PROJECTCOMPATVERSION_Size', 0x0004, projectcompatversion_size) | |
| 1733 | + projectcompatversion_compatversion = struct.unpack("<L", dir_stream.read(4))[0] | |
| 1734 | + # compat version: A 32-bit number that identifies the Office Model version used by a VBA project. | |
| 1735 | + log.debug("compat version: {compat_version}".format(compat_version=projectcompatversion_compatversion)) | |
| 1736 | + | |
| 1737 | + # PROJECTLCID Record | |
| 1738 | + project_id = struct.unpack("<H", dir_stream.read(2))[0] | |
| 1739 | + | |
| 1740 | + projectlcid_id = project_id | |
| 1741 | + | |
| 1724 | 1742 | # Specifies the VBA project's LCID. |
| 1725 | - projectlcid_id = struct.unpack("<H", dir_stream.read(2))[0] | |
| 1726 | 1743 | self.check_value('PROJECTLCID_Id', 0x0002, projectlcid_id) |
| 1727 | 1744 | projectlcid_size = struct.unpack("<L", dir_stream.read(4))[0] |
| 1728 | 1745 | self.check_value('PROJECTLCID_Size', 0x0004, projectlcid_size) | ... | ... |
tests/olevba/test_basic.py
| ... | ... | @@ -103,6 +103,24 @@ class TestOlevbaBasic(unittest.TestCase): |
| 103 | 103 | msg='Wrong return code {} for args {}'\ |
| 104 | 104 | .format(ret_code, args + [filename, ])) |
| 105 | 105 | |
| 106 | + def test_dir_stream_record_project_compat_version(self): | |
| 107 | + """Test PROJECTCOMPATVERSION record on dir stream with a ppt file.""" | |
| 108 | + input_file = join(DATA_BASE_DIR, 'olevba', 'sample_with_vba.ppt') | |
| 109 | + output, ret_code = call_and_capture('olevba', args=(input_file, "--loglevel", "debug")) | |
| 110 | + | |
| 111 | + # check return code | |
| 112 | + self.assertEqual(ret_code, 0) | |
| 113 | + | |
| 114 | + # not expected string: | |
| 115 | + self.assertNotIn('invalid value for PROJECTLCID_Id expected 0002 got', output) | |
| 116 | + self.assertNotIn('Error in _extract_vba', output) | |
| 117 | + | |
| 118 | + # compat version in debug mode: | |
| 119 | + self.assertIn('compat version: 2', output) | |
| 120 | + | |
| 121 | + # vba contents: | |
| 122 | + self.assertIn('Sub Action_Click()\n MsgBox "The action button clicked!"\nEnd Sub', output) | |
| 123 | + | |
| 106 | 124 | |
| 107 | 125 | # just in case somebody calls this file as a script |
| 108 | 126 | if __name__ == '__main__': | ... | ... |
tests/test-data/olevba/sample_with_vba.ppt
0 → 100644
No preview for this file type