Commit 249db149ced4c76dbfe4314d28ce0ae7a6458a99
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: | ... | ... |