Commit 49b8af644038bf4ceaa3a7c51f057f5f111c0346
1 parent
4b4775d3
olevba: added new option --reveal
Showing
1 changed file
with
32 additions
and
4 deletions
oletools/olevba.py
| @@ -151,8 +151,9 @@ https://github.com/unixfreak0037/officeparser | @@ -151,8 +151,9 @@ https://github.com/unixfreak0037/officeparser | ||
| 151 | # 2015-09-15 PL: - remove duplicate IOCs from results | 151 | # 2015-09-15 PL: - remove duplicate IOCs from results |
| 152 | # 2015-09-16 PL: - join long VBA lines ending with underscore before scan | 152 | # 2015-09-16 PL: - join long VBA lines ending with underscore before scan |
| 153 | # - disabled unused option --each | 153 | # - disabled unused option --each |
| 154 | +# 2015-09-22 v0.41 PL: - added new option --reveal | ||
| 154 | 155 | ||
| 155 | -__version__ = '0.40' | 156 | +__version__ = '0.41' |
| 156 | 157 | ||
| 157 | #------------------------------------------------------------------------------ | 158 | #------------------------------------------------------------------------------ |
| 158 | # TODO: | 159 | # TODO: |
| @@ -2095,9 +2096,30 @@ class VBA_Parser_CLI(VBA_Parser): | @@ -2095,9 +2096,30 @@ class VBA_Parser_CLI(VBA_Parser): | ||
| 2095 | print 'No suspicious keyword or IOC found.' | 2096 | print 'No suspicious keyword or IOC found.' |
| 2096 | 2097 | ||
| 2097 | 2098 | ||
| 2099 | + def reveal(self): | ||
| 2100 | + print 'MACRO SOURCE CODE WITH DEOBFUSCATED VBA STRINGS (EXPERIMENTAL):\n' | ||
| 2101 | + # we only want printable strings: | ||
| 2102 | + analysis = self.analyze_macros(show_decoded_strings=False) | ||
| 2103 | + # to avoid replacing short strings contained into longer strings, we sort the analysis results | ||
| 2104 | + # based on the length of the encoded string, in reverse order: | ||
| 2105 | + analysis = sorted(analysis, key=lambda type_decoded_encoded: len(type_decoded_encoded[2]), reverse=True) | ||
| 2106 | + # normally now self.vba_code_all_modules contains source code from all modules | ||
| 2107 | + deobf_code = self.vba_code_all_modules | ||
| 2108 | + for kw_type, decoded, encoded in analysis: | ||
| 2109 | + if kw_type == 'VBA string': | ||
| 2110 | + #print '%3d occurences: %r => %r' % (deobf_code.count(encoded), encoded, decoded) | ||
| 2111 | + # need to add double quotes around the decoded strings | ||
| 2112 | + # after escaping double-quotes as double-double-quotes for VBA: | ||
| 2113 | + decoded = decoded.replace('"', '""') | ||
| 2114 | + deobf_code = deobf_code.replace(encoded, '"%s"' % decoded) | ||
| 2115 | + print '' | ||
| 2116 | + print deobf_code | ||
| 2117 | + #TODO: repasser l'analyse plusieurs fois si des chaines hex ou base64 sont revelees | ||
| 2118 | + | ||
| 2119 | + | ||
| 2098 | def process_file(self, show_decoded_strings=False, | 2120 | def process_file(self, show_decoded_strings=False, |
| 2099 | display_code=True, global_analysis=True, hide_attributes=True, | 2121 | display_code=True, global_analysis=True, hide_attributes=True, |
| 2100 | - vba_code_only=False): | 2122 | + vba_code_only=False, show_deobfuscated_code=False): |
| 2101 | """ | 2123 | """ |
| 2102 | Process a single file | 2124 | Process a single file |
| 2103 | 2125 | ||
| @@ -2150,6 +2172,8 @@ class VBA_Parser_CLI(VBA_Parser): | @@ -2150,6 +2172,8 @@ class VBA_Parser_CLI(VBA_Parser): | ||
| 2150 | if global_analysis and not vba_code_only: | 2172 | if global_analysis and not vba_code_only: |
| 2151 | # analyse the code from all modules at once: | 2173 | # analyse the code from all modules at once: |
| 2152 | self.print_analysis(show_decoded_strings) | 2174 | self.print_analysis(show_decoded_strings) |
| 2175 | + if show_deobfuscated_code: | ||
| 2176 | + self.reveal() | ||
| 2153 | else: | 2177 | else: |
| 2154 | print 'No VBA macros found.' | 2178 | print 'No VBA macros found.' |
| 2155 | except: #TypeError: | 2179 | except: #TypeError: |
| @@ -2260,6 +2284,8 @@ def main(): | @@ -2260,6 +2284,8 @@ def main(): | ||
| 2260 | help='display all the obfuscated strings with their decoded content (Hex, Base64, StrReverse, Dridex, VBA).') | 2284 | help='display all the obfuscated strings with their decoded content (Hex, Base64, StrReverse, Dridex, VBA).') |
| 2261 | parser.add_option("--attr", action="store_false", dest="hide_attributes", default=True, | 2285 | parser.add_option("--attr", action="store_false", dest="hide_attributes", default=True, |
| 2262 | help='display the attribute lines at the beginning of VBA source code') | 2286 | help='display the attribute lines at the beginning of VBA source code') |
| 2287 | + parser.add_option("--reveal", action="store_true", dest="show_deobfuscated_code", | ||
| 2288 | + help='display the macro source code after replacing all the obfuscated strings by their decoded content.') | ||
| 2263 | 2289 | ||
| 2264 | # Disabled options: | 2290 | # Disabled options: |
| 2265 | # parser.add_option("--each", action="store_false", dest="global_analysis", default=True, | 2291 | # parser.add_option("--each", action="store_false", dest="global_analysis", default=True, |
| @@ -2316,7 +2342,8 @@ def main(): | @@ -2316,7 +2342,8 @@ def main(): | ||
| 2316 | # fully detailed output | 2342 | # fully detailed output |
| 2317 | vba_parser.process_file(show_decoded_strings=options.show_decoded_strings, | 2343 | vba_parser.process_file(show_decoded_strings=options.show_decoded_strings, |
| 2318 | display_code=options.display_code, global_analysis=True, #options.global_analysis, | 2344 | display_code=options.display_code, global_analysis=True, #options.global_analysis, |
| 2319 | - hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only) | 2345 | + hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only, |
| 2346 | + show_deobfuscated_code=options.show_deobfuscated_code) | ||
| 2320 | else: | 2347 | else: |
| 2321 | # print container name when it changes: | 2348 | # print container name when it changes: |
| 2322 | if container != previous_container: | 2349 | if container != previous_container: |
| @@ -2335,7 +2362,8 @@ def main(): | @@ -2335,7 +2362,8 @@ def main(): | ||
| 2335 | # if options -t and -d were not specified and it's a single file, print details: | 2362 | # if options -t and -d were not specified and it's a single file, print details: |
| 2336 | vba_parser.process_file(show_decoded_strings=options.show_decoded_strings, | 2363 | vba_parser.process_file(show_decoded_strings=options.show_decoded_strings, |
| 2337 | display_code=options.display_code, global_analysis=True, #options.global_analysis, | 2364 | display_code=options.display_code, global_analysis=True, #options.global_analysis, |
| 2338 | - hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only) | 2365 | + hide_attributes=options.hide_attributes, vba_code_only=options.vba_code_only, |
| 2366 | + show_deobfuscated_code=options.show_deobfuscated_code) | ||
| 2339 | 2367 | ||
| 2340 | 2368 | ||
| 2341 | if __name__ == '__main__': | 2369 | if __name__ == '__main__': |