Commit 7b3697b3c5795794bd016fde463aae9ec46db3fc
1 parent
1892bb00
olevba: added option --pcode to disassemble and display the VBA P-Code using pcodedmp
Showing
3 changed files
with
28 additions
and
3 deletions
oletools/olevba.py
| ... | ... | @@ -216,8 +216,9 @@ from __future__ import print_function |
| 216 | 216 | # 2019-03-18 PL: - added XLM/XLF macros detection for Excel OLE files |
| 217 | 217 | # 2019-03-25 CH: - added decryption of password-protected files |
| 218 | 218 | # 2019-04-09 PL: - decompress_stream accepts bytes (issue #422) |
| 219 | +# 2019-05-23 v0.55 PL: - added option --pcode to call pcodedmp and display P-code | |
| 219 | 220 | |
| 220 | -__version__ = '0.54.2' | |
| 221 | +__version__ = '0.55.dev1' | |
| 221 | 222 | |
| 222 | 223 | #------------------------------------------------------------------------------ |
| 223 | 224 | # TODO: |
| ... | ... | @@ -285,6 +286,7 @@ except ImportError: |
| 285 | 286 | + "or http://effbot.org/zone/element-index.htm") |
| 286 | 287 | |
| 287 | 288 | import colorclass |
| 289 | +from pcodedmp import pcodedmp | |
| 288 | 290 | |
| 289 | 291 | # On Windows, colorclass needs to be enabled: |
| 290 | 292 | if os.name == 'nt': |
| ... | ... | @@ -3518,7 +3520,7 @@ class VBA_Parser_CLI(VBA_Parser): |
| 3518 | 3520 | def process_file(self, show_decoded_strings=False, |
| 3519 | 3521 | display_code=True, hide_attributes=True, |
| 3520 | 3522 | vba_code_only=False, show_deobfuscated_code=False, |
| 3521 | - deobfuscate=False): | |
| 3523 | + deobfuscate=False, pcode=False): | |
| 3522 | 3524 | """ |
| 3523 | 3525 | Process a single file |
| 3524 | 3526 | |
| ... | ... | @@ -3530,6 +3532,7 @@ class VBA_Parser_CLI(VBA_Parser): |
| 3530 | 3532 | otherwise each module is analyzed separately (old behaviour) |
| 3531 | 3533 | :param hide_attributes: bool, if True the first lines starting with "Attribute VB" are hidden (default) |
| 3532 | 3534 | :param deobfuscate: bool, if True attempt to deobfuscate VBA expressions (slow) |
| 3535 | + :param pcode bool: if True, call pcodedmp to disassemble P-code and display it | |
| 3533 | 3536 | """ |
| 3534 | 3537 | #TODO: replace print by writing to a provided output file (sys.stdout by default) |
| 3535 | 3538 | # fix conflicting parameters: |
| ... | ... | @@ -3599,6 +3602,23 @@ class VBA_Parser_CLI(VBA_Parser): |
| 3599 | 3602 | # display the exception with full stack trace for debugging |
| 3600 | 3603 | log.info('Error parsing form: %s' % exc) |
| 3601 | 3604 | log.debug('Traceback:', exc_info=True) |
| 3605 | + if pcode: | |
| 3606 | + print('-' * 79) | |
| 3607 | + print('P-CODE disassembly:') | |
| 3608 | + # save sys.stdout, then modify it to capture pcodedmp's output | |
| 3609 | + stdout = sys.stdout | |
| 3610 | + output = BytesIO() | |
| 3611 | + sys.stdout = output | |
| 3612 | + class args: | |
| 3613 | + disasmOnly = True | |
| 3614 | + verbose = False | |
| 3615 | + try: | |
| 3616 | + # TODO: handle files in memory too | |
| 3617 | + pcodedmp.processFile(self.filename, args) | |
| 3618 | + except Exception: | |
| 3619 | + log.error('Error while running pcodedmp') | |
| 3620 | + sys.stdout = stdout | |
| 3621 | + print(output.getvalue()) | |
| 3602 | 3622 | |
| 3603 | 3623 | if not vba_code_only: |
| 3604 | 3624 | # analyse the code from all modules at once: |
| ... | ... | @@ -3786,6 +3806,8 @@ def parse_args(cmd_line_args=None): |
| 3786 | 3806 | help="Attempt to deobfuscate VBA expressions (slow)") |
| 3787 | 3807 | parser.add_option('--relaxed', dest="relaxed", action="store_true", default=False, |
| 3788 | 3808 | help="Do not raise errors if opening of substream fails") |
| 3809 | + parser.add_option('--pcode', dest="pcode", action="store_true", default=False, | |
| 3810 | + help="Disassemble and display the P-code (using pcodedmp)") | |
| 3789 | 3811 | |
| 3790 | 3812 | (options, args) = parser.parse_args(cmd_line_args) |
| 3791 | 3813 | |
| ... | ... | @@ -3823,7 +3845,7 @@ def process_file(filename, data, container, options, crypto_nesting=0): |
| 3823 | 3845 | display_code=options.display_code, |
| 3824 | 3846 | hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only, |
| 3825 | 3847 | show_deobfuscated_code=options.show_deobfuscated_code, |
| 3826 | - deobfuscate=options.deobfuscate) | |
| 3848 | + deobfuscate=options.deobfuscate, pcode=options.pcode) | |
| 3827 | 3849 | elif options.output_mode == 'triage': |
| 3828 | 3850 | # summarized output for triage: |
| 3829 | 3851 | vba_parser.process_file_triage(show_decoded_strings=options.show_decoded_strings, | ... | ... |
requirements.txt
setup.py
| ... | ... | @@ -30,6 +30,7 @@ to install this package. |
| 30 | 30 | # 2018-10-27 PL: - fixed issue #359 (bug when importing log_helper) |
| 31 | 31 | # 2019-02-26 CH: - add optional dependency msoffcrypto for decryption |
| 32 | 32 | # 2019-05-22 PL: - 'msoffcrypto-tool' is now a required dependency |
| 33 | +# 2019-05-23 v0.55 PL: - added pcodedmp as dependency | |
| 33 | 34 | |
| 34 | 35 | #--- TODO --------------------------------------------------------------------- |
| 35 | 36 | |
| ... | ... | @@ -319,6 +320,7 @@ def main(): |
| 319 | 320 | "easygui", |
| 320 | 321 | 'colorclass', |
| 321 | 322 | 'msoffcrypto-tool', |
| 323 | + 'pcodedmp>=1.2.4', | |
| 322 | 324 | ], |
| 323 | 325 | ) |
| 324 | 326 | ... | ... |