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,8 +87,9 @@ Usage: olevba.py <file> | ||
| 87 | # 2014-12-14 v0.07 PL: - detect_autoexec() is now case-insensitive | 87 | # 2014-12-14 v0.07 PL: - detect_autoexec() is now case-insensitive |
| 88 | # 2014-12-15 v0.08 PL: - improved display for empty macros | 88 | # 2014-12-15 v0.08 PL: - improved display for empty macros |
| 89 | # - added pattern extraction | 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 | # TODO: | 95 | # TODO: |
| @@ -162,6 +163,36 @@ AUTOEXEC_KEYWORDS = { | @@ -162,6 +163,36 @@ AUTOEXEC_KEYWORDS = { | ||
| 162 | #TODO: full list in MS specs?? | 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 | # Patterns to be extracted (IP addresses, URLs, etc) | 196 | # Patterns to be extracted (IP addresses, URLs, etc) |
| 166 | # From patterns.py in balbuzard | 197 | # From patterns.py in balbuzard |
| 167 | RE_PATTERNS = ( | 198 | RE_PATTERNS = ( |
| @@ -726,6 +757,26 @@ def detect_autoexec(vba_code): | @@ -726,6 +757,26 @@ def detect_autoexec(vba_code): | ||
| 726 | return results | 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 | def detect_patterns(vba_code): | 780 | def detect_patterns(vba_code): |
| 730 | """ | 781 | """ |
| 731 | Detect if the VBA code contains specific patterns such as IP addresses, | 782 | Detect if the VBA code contains specific patterns such as IP addresses, |
| @@ -1001,6 +1052,20 @@ if __name__ == '__main__': | @@ -1001,6 +1052,20 @@ if __name__ == '__main__': | ||
| 1001 | print 'Auto-executable macro keywords: None found' | 1052 | print 'Auto-executable macro keywords: None found' |
| 1002 | 1053 | ||
| 1003 | print '- '*39 | 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 | patterns = detect_patterns(vba_code) | 1069 | patterns = detect_patterns(vba_code) |
| 1005 | if patterns: | 1070 | if patterns: |
| 1006 | print 'Patterns found:' | 1071 | print 'Patterns found:' |