Commit d353c6d94dfe08154958db5ee2ef7f53469621e5
Merge pull request #44 from christian-intra2net/fix-deof-with-json
Fix --deobf option for JSON output
Showing
2 changed files
with
18 additions
and
46 deletions
oletools/olevba.py
| ... | ... | @@ -2771,12 +2771,14 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2771 | 2771 | else: |
| 2772 | 2772 | print 'No suspicious keyword or IOC found.' |
| 2773 | 2773 | |
| 2774 | - def print_analysis_json(self, show_decoded_strings=False): | |
| 2774 | + def print_analysis_json(self, show_decoded_strings=False, deobfuscate=False): | |
| 2775 | 2775 | """ |
| 2776 | 2776 | Analyze the provided VBA code, and return the results in json format |
| 2777 | 2777 | |
| 2778 | 2778 | :param vba_code: str, VBA source code to be analyzed |
| 2779 | 2779 | :param show_decoded_strings: bool, if True hex-encoded strings will be displayed with their decoded content. |
| 2780 | + :param deobfuscate: bool, if True attempt to deobfuscate VBA expressions (slow) | |
| 2781 | + | |
| 2780 | 2782 | :return: dict |
| 2781 | 2783 | """ |
| 2782 | 2784 | # print a waiting message only if the output is not redirected to a file: |
| ... | ... | @@ -2784,7 +2786,7 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2784 | 2786 | print 'Analysis...\r', |
| 2785 | 2787 | sys.stdout.flush() |
| 2786 | 2788 | return [dict(type=kw_type, keyword=keyword, description=description) |
| 2787 | - for kw_type, keyword, description in self.analyze_macros(show_decoded_strings)] | |
| 2789 | + for kw_type, keyword, description in self.analyze_macros(show_decoded_strings, deobfuscate)] | |
| 2788 | 2790 | |
| 2789 | 2791 | def process_file(self, show_decoded_strings=False, |
| 2790 | 2792 | display_code=True, hide_attributes=True, |
| ... | ... | @@ -2856,7 +2858,8 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2856 | 2858 | |
| 2857 | 2859 | def process_file_json(self, show_decoded_strings=False, |
| 2858 | 2860 | display_code=True, hide_attributes=True, |
| 2859 | - vba_code_only=False, show_deobfuscated_code=False): | |
| 2861 | + vba_code_only=False, show_deobfuscated_code=False, | |
| 2862 | + deobfuscate=False): | |
| 2860 | 2863 | """ |
| 2861 | 2864 | Process a single file |
| 2862 | 2865 | |
| ... | ... | @@ -2869,6 +2872,7 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2869 | 2872 | :param global_analysis: bool, if True all modules are merged for a single analysis (default), |
| 2870 | 2873 | otherwise each module is analyzed separately (old behaviour) |
| 2871 | 2874 | :param hide_attributes: bool, if True the first lines starting with "Attribute VB" are hidden (default) |
| 2875 | + :param deobfuscate: bool, if True attempt to deobfuscate VBA expressions (slow) | |
| 2872 | 2876 | """ |
| 2873 | 2877 | #TODO: fix conflicting parameters (?) |
| 2874 | 2878 | |
| ... | ... | @@ -2885,6 +2889,7 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2885 | 2889 | result['json_conversion_successful'] = False |
| 2886 | 2890 | result['analysis'] = None |
| 2887 | 2891 | result['code_deobfuscated'] = None |
| 2892 | + result['do_deobfuscate'] = deobfuscate | |
| 2888 | 2893 | |
| 2889 | 2894 | try: |
| 2890 | 2895 | #TODO: handle olefile errors, when an OLE file is malformed |
| ... | ... | @@ -2904,10 +2909,13 @@ class VBA_Parser_CLI(VBA_Parser): |
| 2904 | 2909 | curr_macro['ole_stream'] = stream_path |
| 2905 | 2910 | if display_code: |
| 2906 | 2911 | curr_macro['code'] = vba_code_filtered.strip() |
| 2912 | + else: | |
| 2913 | + curr_macro['code'] = None | |
| 2907 | 2914 | macros.append(curr_macro) |
| 2908 | 2915 | if not vba_code_only: |
| 2909 | 2916 | # analyse the code from all modules at once: |
| 2910 | - result['analysis'] = self.print_analysis_json(show_decoded_strings) | |
| 2917 | + result['analysis'] = self.print_analysis_json(show_decoded_strings, | |
| 2918 | + deobfuscate) | |
| 2911 | 2919 | if show_deobfuscated_code: |
| 2912 | 2920 | result['code_deobfuscated'] = self.reveal() |
| 2913 | 2921 | result['macros'] = macros |
| ... | ... | @@ -3063,7 +3071,10 @@ def main(): |
| 3063 | 3071 | |
| 3064 | 3072 | # with the option --reveal, make sure --deobf is also enabled: |
| 3065 | 3073 | if options.show_deobfuscated_code and not options.deobfuscate: |
| 3074 | + log.info('set --deobf because --reveal was set') | |
| 3066 | 3075 | options.deobfuscate = True |
| 3076 | + if options.output_mode == 'triage' and options.show_deobfuscated_code: | |
| 3077 | + log.info('ignoring option --reveal in triage output mode') | |
| 3067 | 3078 | |
| 3068 | 3079 | # Column headers (do not know how many files there will be yet, so if no output_mode |
| 3069 | 3080 | # was specified, we will print triage for first file --> need these headers) |
| ... | ... | @@ -3130,7 +3141,8 @@ def main(): |
| 3130 | 3141 | vba_parser.process_file_json(show_decoded_strings=options.show_decoded_strings, |
| 3131 | 3142 | display_code=options.display_code, |
| 3132 | 3143 | hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only, |
| 3133 | - show_deobfuscated_code=options.show_deobfuscated_code)) | |
| 3144 | + show_deobfuscated_code=options.show_deobfuscated_code, | |
| 3145 | + deobfuscate=options.deobfuscate)) | |
| 3134 | 3146 | else: # (should be impossible) |
| 3135 | 3147 | raise ValueError('unexpected output mode: "{0}"!'.format(options.output_mode)) |
| 3136 | 3148 | count += 1 | ... | ... |
oletools/ppt_parser.py
| ... | ... | @@ -1568,46 +1568,6 @@ def iterative_decompress(stream, size, chunk_size=4096): |
| 1568 | 1568 | |
| 1569 | 1569 | return decomp, n_read, return_err |
| 1570 | 1570 | |
| 1571 | -# === TESTING ================================================================= | |
| 1572 | - | |
| 1573 | -def test(): | |
| 1574 | - """ for testing and debugging """ | |
| 1575 | - | |
| 1576 | - from glob import glob | |
| 1577 | - from olevba import VBA_Parser | |
| 1578 | - | |
| 1579 | - # setup logging | |
| 1580 | - logging.basicConfig(level=logging.DEBUG, | |
| 1581 | - format='%(levelname)-8s %(name)s: %(message)s') | |
| 1582 | - log.setLevel(logging.NOTSET) | |
| 1583 | - | |
| 1584 | - test_files = ['gelaber_autostart.ppt', ] | |
| 1585 | - #test_files = glob('*.ppt') | |
| 1586 | - for file_name in test_files: | |
| 1587 | - # parse | |
| 1588 | - log.info('-' * 72) | |
| 1589 | - log.info('test file: {}'.format(file_name)) | |
| 1590 | - try: | |
| 1591 | - ppt = PptParser(file_name, fast_fail=False) | |
| 1592 | - #ppt.parse_document_persist_object() | |
| 1593 | - | |
| 1594 | - for vba_data in ppt.iter_vba_data(): | |
| 1595 | - parser = VBA_Parser(None, vba_data, container='PptParser') | |
| 1596 | - for vba_root, project_path, dir_path in \ | |
| 1597 | - parser.find_vba_projects(): | |
| 1598 | - log.info('found vba project: root={}, proj={}, dir={}' | |
| 1599 | - .format(vba_root, project_path, dir_path)) | |
| 1600 | - for subfilename, stream_path, vba_filename, vba_code in \ | |
| 1601 | - parser.extract_all_macros(): | |
| 1602 | - log.info('found macro: subfile={}, stream={}, vbafile={}' | |
| 1603 | - .format(subfilename, stream_path, vba_filename)) | |
| 1604 | - for line in vba_code.splitlines(): | |
| 1605 | - log.info('code: {}'.format(line.rstrip())) | |
| 1606 | - | |
| 1607 | - | |
| 1608 | - except Exception: | |
| 1609 | - log.exception('exception') | |
| 1610 | - | |
| 1611 | 1571 | |
| 1612 | 1572 | if __name__ == '__main__': |
| 1613 | - test() | |
| 1573 | + print 'nothing here to run!' | ... | ... |