Commit 49b8af644038bf4ceaa3a7c51f057f5f111c0346

Authored by Philippe Lagadec
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 151 # 2015-09-15 PL: - remove duplicate IOCs from results
152 152 # 2015-09-16 PL: - join long VBA lines ending with underscore before scan
153 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 159 # TODO:
... ... @@ -2095,9 +2096,30 @@ class VBA_Parser_CLI(VBA_Parser):
2095 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 2120 def process_file(self, show_decoded_strings=False,
2099 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 2124 Process a single file
2103 2125  
... ... @@ -2150,6 +2172,8 @@ class VBA_Parser_CLI(VBA_Parser):
2150 2172 if global_analysis and not vba_code_only:
2151 2173 # analyse the code from all modules at once:
2152 2174 self.print_analysis(show_decoded_strings)
  2175 + if show_deobfuscated_code:
  2176 + self.reveal()
2153 2177 else:
2154 2178 print 'No VBA macros found.'
2155 2179 except: #TypeError:
... ... @@ -2260,6 +2284,8 @@ def main():
2260 2284 help='display all the obfuscated strings with their decoded content (Hex, Base64, StrReverse, Dridex, VBA).')
2261 2285 parser.add_option("--attr", action="store_false", dest="hide_attributes", default=True,
2262 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 2290 # Disabled options:
2265 2291 # parser.add_option("--each", action="store_false", dest="global_analysis", default=True,
... ... @@ -2316,7 +2342,8 @@ def main():
2316 2342 # fully detailed output
2317 2343 vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
2318 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 2347 else:
2321 2348 # print container name when it changes:
2322 2349 if container != previous_container:
... ... @@ -2335,7 +2362,8 @@ def main():
2335 2362 # if options -t and -d were not specified and it's a single file, print details:
2336 2363 vba_parser.process_file(show_decoded_strings=options.show_decoded_strings,
2337 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 2369 if __name__ == '__main__':
... ...