Commit 249db149ced4c76dbfe4314d28ce0ae7a6458a99

Authored by Philippe Lagadec
1 parent 1586b7e9

olevba: added option -i to analyze VBA source code directly

Showing 1 changed file with 43 additions and 23 deletions
oletools/olevba.py
... ... @@ -101,6 +101,7 @@ https://github.com/unixfreak0037/officeparser
101 101 # 2015-01-11 v0.15 PL: - added new triage mode, options -t and -d
102 102 # 2015-01-16 v0.16 PL: - fix for issue #3 (exception when module name="text")
103 103 # - added several suspicious keywords
  104 +# - added option -i to analyze VBA source code directly
104 105  
105 106 __version__ = '0.16'
106 107  
... ... @@ -1098,6 +1099,37 @@ class VBA_Parser(object):
1098 1099 self.ole_file.close()
1099 1100  
1100 1101  
  1102 +def print_analysis(vba_code):
  1103 + """
  1104 + Analyze the provided VBA code, and print the results in a table
  1105 +
  1106 + :param vba_code: str, VBA source code to be analyzed
  1107 + :return: None
  1108 + """
  1109 + autoexec_keywords = detect_autoexec(vba_code)
  1110 + suspicious_keywords = detect_suspicious(vba_code)
  1111 + patterns = detect_patterns(vba_code)
  1112 + hex_strings = detect_hex_strings(vba_code)
  1113 + if autoexec_keywords or suspicious_keywords or patterns:
  1114 + t = prettytable.PrettyTable(('Type', 'Keyword', 'Description'))
  1115 + t.align = 'l'
  1116 + t.max_width['Type'] = 10
  1117 + t.max_width['Keyword'] = 20
  1118 + t.max_width['Description'] = 39
  1119 + for keyword, description in autoexec_keywords:
  1120 + t.add_row(('AutoExec', keyword, description))
  1121 + for keyword, description in suspicious_keywords:
  1122 + t.add_row(('Suspicious', keyword, description))
  1123 + for pattern_type, value in patterns:
  1124 + t.add_row(('IOC', value, pattern_type))
  1125 + for encoded, decoded in hex_strings:
  1126 + t.add_row(('Hex String', repr(decoded), encoded))
  1127 + print t
  1128 + else:
  1129 + print 'No suspicious keyword or pattern found.'
  1130 +
  1131 +
  1132 +
1101 1133 def process_file (container, filename, data):
1102 1134 """
1103 1135 Process a single file
... ... @@ -1134,28 +1166,7 @@ def process_file (container, filename, data):
1134 1166 print vba_code
1135 1167 print '- '*39
1136 1168 print 'ANALYSIS:'
1137   - autoexec_keywords = detect_autoexec(vba_code)
1138   - suspicious_keywords = detect_suspicious(vba_code)
1139   - patterns = detect_patterns(vba_code)
1140   - hex_strings = detect_hex_strings(vba_code)
1141   - if autoexec_keywords or suspicious_keywords or patterns:
1142   - t = prettytable.PrettyTable(('Type', 'Keyword', 'Description'))
1143   - t.align = 'l'
1144   - t.max_width['Type'] = 10
1145   - t.max_width['Keyword'] = 20
1146   - t.max_width['Description'] = 39
1147   - for keyword, description in autoexec_keywords:
1148   - t.add_row(('AutoExec', keyword, description))
1149   - for keyword, description in suspicious_keywords:
1150   - t.add_row(('Suspicious', keyword, description))
1151   - for pattern_type, value in patterns:
1152   - t.add_row(('IOC', value, pattern_type))
1153   - for encoded, decoded in hex_strings:
1154   - t.add_row(('Hex String', repr(decoded), encoded))
1155   - print t
1156   - else:
1157   - print 'No suspicious keyword or pattern found.'
1158   -
  1169 + print_analysis(vba_code)
1159 1170 else:
1160 1171 print 'No VBA macros found.'
1161 1172 except: #TypeError:
... ... @@ -1267,11 +1278,13 @@ def main():
1267 1278 help='triage mode, display results as a summary table (default for multiple files)')
1268 1279 parser.add_option("-d", action="store_true", dest="detailed_mode",
1269 1280 help='detailed mode, display full results (default for single file)')
  1281 + parser.add_option("-i", "--input", dest='input', type='str', default=None,
  1282 + help='input file containing VBA source code to be analyzed (no parsing)')
1270 1283  
1271 1284 (options, args) = parser.parse_args()
1272 1285  
1273 1286 # Print help if no arguments are passed
1274   - if len(args) == 0:
  1287 + if len(args) == 0 and not options.input:
1275 1288 print __doc__
1276 1289 parser.print_help()
1277 1290 sys.exit()
... ... @@ -1280,6 +1293,13 @@ def main():
1280 1293 # For now, all logging is disabled:
1281 1294 logging.disable(logging.CRITICAL)
1282 1295  
  1296 + if options.input:
  1297 + # input file provided with VBA source code to be analyzed directly:
  1298 + print 'Analysis of VBA source code from %s:' % options.input
  1299 + vba_code = open(options.input).read()
  1300 + print_analysis(vba_code)
  1301 + sys.exit()
  1302 +
1283 1303 # print '%-8s %-7s %-7s %-7s %-7s %-7s' % ('Type', 'Macros', 'AutoEx', 'Susp.', 'IOCs', 'HexStr')
1284 1304 # print '%-8s %-7s %-7s %-7s %-7s %-7s' % ('-'*8, '-'*7, '-'*7, '-'*7, '-'*7, '-'*7)
1285 1305 if not options.detailed_mode or options.triage_mode:
... ...