Commit a136731b24ddb2d9ce938d79d6f3123d77c454a6
1 parent
99e9238e
olevba: added suspicious keywords detection
Showing
1 changed file
with
66 additions
and
1 deletions
oletools/olevba.py
| ... | ... | @@ -87,8 +87,9 @@ Usage: olevba.py <file> |
| 87 | 87 | # 2014-12-14 v0.07 PL: - detect_autoexec() is now case-insensitive |
| 88 | 88 | # 2014-12-15 v0.08 PL: - improved display for empty macros |
| 89 | 89 | # - added pattern extraction |
| 90 | +# 2014-12-25 v0.09 PL: - added suspicious keywords detection | |
| 90 | 91 | |
| 91 | -__version__ = '0.08' | |
| 92 | +__version__ = '0.09' | |
| 92 | 93 | |
| 93 | 94 | #------------------------------------------------------------------------------ |
| 94 | 95 | # TODO: |
| ... | ... | @@ -162,6 +163,36 @@ AUTOEXEC_KEYWORDS = { |
| 162 | 163 | #TODO: full list in MS specs?? |
| 163 | 164 | } |
| 164 | 165 | |
| 166 | +# Suspicious Keywords that may be used by malware | |
| 167 | +SUSPICIOUS_KEYWORDS = { | |
| 168 | + #TODO: use regex to support variable whitespaces | |
| 169 | + 'May read system environment variables': | |
| 170 | + ('environ',), | |
| 171 | + 'May open a file': | |
| 172 | + ('open',), | |
| 173 | + 'May write to a file (if combined with Open)': | |
| 174 | + ('write', 'put', 'output', 'print #'), | |
| 175 | + 'May read or write a binary file (if combined with Open)': | |
| 176 | + ('binary',), | |
| 177 | + 'May run an executable file or a system command': | |
| 178 | + ('shell', 'vbnormalfocus'), | |
| 179 | + 'May hide the application': | |
| 180 | + ('Application.Visible', 'ShowWindow', 'SW_HIDE'), | |
| 181 | + 'May create a directory': | |
| 182 | + ('MkDir',), | |
| 183 | + 'May save the current workbook': | |
| 184 | + ('ActiveWorkbook.SaveAs',), | |
| 185 | + 'May change which directory contains files to open at startup': | |
| 186 | + #TODO: confirm the actual effect | |
| 187 | + ('Application.AltStartupPath',), | |
| 188 | + 'May create an OLE object': | |
| 189 | + ('CreateObject',), | |
| 190 | + 'May run an application (if combined with CreateObject)': | |
| 191 | + ('Shell.Application',), | |
| 192 | + 'May enumerate application windows (if combined with Shell.Application object)': | |
| 193 | + ('.Windows', 'FindWindow'), | |
| 194 | +} | |
| 195 | + | |
| 165 | 196 | # Patterns to be extracted (IP addresses, URLs, etc) |
| 166 | 197 | # From patterns.py in balbuzard |
| 167 | 198 | RE_PATTERNS = ( |
| ... | ... | @@ -726,6 +757,26 @@ def detect_autoexec(vba_code): |
| 726 | 757 | return results |
| 727 | 758 | |
| 728 | 759 | |
| 760 | +def detect_suspicious(vba_code): | |
| 761 | + """ | |
| 762 | + Detect if the VBA code contains suspicious keywords corresponding to | |
| 763 | + potential malware behaviour. | |
| 764 | + | |
| 765 | + :param vba_code: str, VBA source code | |
| 766 | + :return: list of str tuples (keyword, description) | |
| 767 | + """ | |
| 768 | + #TODO: use regex to find keywords with word boundaries | |
| 769 | + # case-insensitive search | |
| 770 | + #vba_code = vba_code.lower() | |
| 771 | + results = [] | |
| 772 | + for description, keywords in SUSPICIOUS_KEYWORDS.items(): | |
| 773 | + for keyword in keywords: | |
| 774 | + if re.search(r'(?i)\b'+keyword+r'\b', vba_code): | |
| 775 | + #if keyword.lower() in vba_code: | |
| 776 | + results.append((keyword, description)) | |
| 777 | + return results | |
| 778 | + | |
| 779 | + | |
| 729 | 780 | def detect_patterns(vba_code): |
| 730 | 781 | """ |
| 731 | 782 | Detect if the VBA code contains specific patterns such as IP addresses, |
| ... | ... | @@ -1001,6 +1052,20 @@ if __name__ == '__main__': |
| 1001 | 1052 | print 'Auto-executable macro keywords: None found' |
| 1002 | 1053 | |
| 1003 | 1054 | print '- '*39 |
| 1055 | + suspicious_keywords = detect_suspicious(vba_code) | |
| 1056 | + if suspicious_keywords: | |
| 1057 | + print 'Suspicious macro keywords found:' | |
| 1058 | + t = prettytable.PrettyTable(('Keyword', 'Description')) | |
| 1059 | + t.align = 'l' | |
| 1060 | + t.max_width['Keyword'] = 20 | |
| 1061 | + t.max_width['Description'] = 59 | |
| 1062 | + for keyword, description in suspicious_keywords: | |
| 1063 | + t.add_row((keyword, description)) | |
| 1064 | + print t | |
| 1065 | + else: | |
| 1066 | + print 'Suspicious macro keywords: None found' | |
| 1067 | + | |
| 1068 | + print '- '*39 | |
| 1004 | 1069 | patterns = detect_patterns(vba_code) |
| 1005 | 1070 | if patterns: |
| 1006 | 1071 | print 'Patterns found:' | ... | ... |