summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Weiser <michael.weiser@gmx.de>2019-02-22 13:43:52 +0000
committerMichael Weiser <michael.weiser@gmx.de>2019-04-25 12:20:20 +0000
commite6c44a8ca3c2216904731e4d889e53473691c0dc (patch)
treee1af84c58c42d41759c6fbc75173003b0765dae3
parentcb54cc4dda6a43b8b5d6d8ab22518fef27b70c60 (diff)
Allow rules to run to be configured
Make the list of rules to run a section in the ruleset configuration. This allows rules to be reordered and (potentially) run more than once without code changes. This also obsoletes the enabled setting per rule because they're now implicitly enabled if they're listed. Commenting out disables a rule.
-rw-r--r--peekaboo/config.py22
-rw-r--r--peekaboo/locale/de/LC_MESSAGES/peekaboo.mobin4286 -> 4219 bytes
-rw-r--r--peekaboo/locale/de/LC_MESSAGES/peekaboo.po90
-rw-r--r--peekaboo/locale/peekaboo.pot89
-rw-r--r--peekaboo/ruleset/engine.py26
-rw-r--r--peekaboo/ruleset/rules.py2
-rw-r--r--ruleset.conf.sample31
7 files changed, 116 insertions, 144 deletions
diff --git a/peekaboo/config.py b/peekaboo/config.py
index e1da0c4..9215011 100644
--- a/peekaboo/config.py
+++ b/peekaboo/config.py
@@ -293,11 +293,7 @@ class PeekabooRulesetConfig(object):
# - There are no duplicate settings with ConfigParser. The last
# one always wins.
- # special keyword enabled is boolean and has the same behaviour
- # for all rules
- if key.lower() in ['enabled']:
- saved_val = config.getboolean(section, setting)
- elif is_list:
+ if is_list:
saved_val.append(config.get(section, setting))
else:
saved_val = config.get(section, setting)
@@ -313,22 +309,6 @@ class PeekabooRulesetConfig(object):
configuration is present. """
return self.ruleset_config.get(rule)
- def rule_enabled(self, rule):
- """ Check if a rule is enabled. Cases are:
- - no config section for that rule is present
- - enabled keyword is not present in that section or
- - the value of the enabled is True (i.e. yes, true, 1 in the file)
-
- @param rule: Name of the rule to check if enabled or not.
- @type rule: string
- @return: True or False based on above criteria.
- """
- config = self.rule_config(rule)
- if config is None:
- return True
-
- return config.get('enabled', True)
-
def __str__(self):
return '<PeekabooRulesetConfiguration(filepath="%s", %s)>' % \
(self.config_file, self.ruleset_config)
diff --git a/peekaboo/locale/de/LC_MESSAGES/peekaboo.mo b/peekaboo/locale/de/LC_MESSAGES/peekaboo.mo
index dab15b2..6cca488 100644
--- a/peekaboo/locale/de/LC_MESSAGES/peekaboo.mo
+++ b/peekaboo/locale/de/LC_MESSAGES/peekaboo.mo
Binary files differ
diff --git a/peekaboo/locale/de/LC_MESSAGES/peekaboo.po b/peekaboo/locale/de/LC_MESSAGES/peekaboo.po
index 86ff0ac..3a2be9f 100644
--- a/peekaboo/locale/de/LC_MESSAGES/peekaboo.po
+++ b/peekaboo/locale/de/LC_MESSAGES/peekaboo.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PeekabooAV 1.6.2\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2019-04-15 15:41+0000\n"
+"POT-Creation-Date: 2019-04-17 09:12+0000\n"
"PO-Revision-Date: 2019-02-14 22:02+0000\n"
"Last-Translator: Michael Weiser <michael.weiser@gmx.de>\n"
"Language: de\n"
@@ -17,143 +17,138 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.4.0\n"
-#: peekaboo/queuing.py:390
+#: peekaboo/queuing.py:382
msgid "Sample initialization failed"
msgstr "Initialisierung der zu analysierenden Datei fehlgeschlagen"
-#: peekaboo/sample.py:189
+#: peekaboo/sample.py:186
#, python-format
msgid "File \"%s\" %s is being analyzed"
msgstr "Datei \"%s\" %s wird analysiert"
-#: peekaboo/sample.py:242
+#: peekaboo/sample.py:239
#, python-format
msgid "File \"%s\" is considered \"%s\""
msgstr "Die Datei \"%s\" wird als \"%s\" betrachtet"
-#: peekaboo/sample.py:302
+#: peekaboo/sample.py:299
#, python-format
msgid "File \"%s\": %s"
msgstr "Datei \"%s\": %s"
-#: peekaboo/sample.py:498
+#: peekaboo/sample.py:495
#, python-format
msgid "Sample %s successfully submitted to Cuckoo as job %d"
msgstr "Erfolgreich an Cuckoo gegeben %s als Job %d"
-#: peekaboo/server.py:143
+#: peekaboo/server.py:141
msgid "Hello, this is Peekaboo."
msgstr "Hallo das ist Peekaboo"
-#: peekaboo/server.py:176
+#: peekaboo/server.py:174
#, fuzzy
msgid "Error: Invalid JSON in request."
msgstr "FEHLER: Ungültiges JSON."
-#: peekaboo/server.py:181
+#: peekaboo/server.py:179
msgid "ERROR: Invalid data structure."
msgstr "FEHLER: Ungültiges Datenformat."
-#: peekaboo/server.py:188
+#: peekaboo/server.py:186
msgid "ERROR: Incomplete data structure."
msgstr "FEHLER: Unvollständige Datenstruktur."
-#: peekaboo/server.py:195
+#: peekaboo/server.py:193
msgid "ERROR: Path does not exist or no permission to access it."
msgstr "FEHLER: Pfad existiert nicht oder Zugriff verweigert."
-#: peekaboo/server.py:202
+#: peekaboo/server.py:200
msgid "ERRROR: Input is not a file"
msgstr "FEHLER: Eingabe ist keine Datei"
-#: peekaboo/server.py:209
+#: peekaboo/server.py:207
msgid "Error submitting sample to job queue"
msgstr "Fehler beim Einstellen in Warteschlange"
-#: peekaboo/server.py:241
+#: peekaboo/server.py:239
msgid "Files are being analyzed..."
msgstr "Dateien werden analysiert..."
-#: peekaboo/server.py:264
+#: peekaboo/server.py:262
msgid "Peekaboo is shutting down."
msgstr "Peekaboo wird beendet."
-#: peekaboo/server.py:316
+#: peekaboo/server.py:314
#, python-format
msgid "The file collection has been categorized \"%s\""
msgstr "Die Datensammlung wurde als \"%s\" eingestuft"
-#: peekaboo/ruleset/__init__.py:66
+#: peekaboo/ruleset/__init__.py:64
msgid "Rule without result"
msgstr "Regel ohne Ergebnis"
-#: peekaboo/ruleset/__init__.py:70
+#: peekaboo/ruleset/__init__.py:68
#, python-format
msgid "Result \"%s\" of rule %s - %s, analysis continues: %s."
msgstr "Ergebnis \"%s\" der Regel %s - %s, Analyse wird fortgesetzt: %s."
-#: peekaboo/ruleset/__init__.py:72
+#: peekaboo/ruleset/__init__.py:70
msgid "Yes"
msgstr "Ja"
-#: peekaboo/ruleset/__init__.py:72
+#: peekaboo/ruleset/__init__.py:70
msgid "No"
msgstr "Nein"
-#: peekaboo/ruleset/engine.py:88
-#, python-format
-msgid "Rule '%s' is disabled."
-msgstr "Regel '%s' ist deaktiviert."
-
-#: peekaboo/ruleset/engine.py:102
+#: peekaboo/ruleset/engine.py:97
msgid "Rule aborted with error"
msgstr "Regel mit Fehler abgebrochen"
-#: peekaboo/ruleset/rules.py:84
+#: peekaboo/ruleset/rules.py:86
msgid "File is not yet known to the system"
msgstr "Datei ist dem System noch nicht bekannt"
-#: peekaboo/ruleset/rules.py:104
+#: peekaboo/ruleset/rules.py:106
#, python-format
msgid "Failure to determine sample file size: %s"
msgstr "Ermittlung der Dateigröße fehlgeschlagen: %s"
-#: peekaboo/ruleset/rules.py:109
+#: peekaboo/ruleset/rules.py:111
#, python-format
msgid "File has more than %d bytes"
msgstr "Datei hat mehr als %d bytes"
-#: peekaboo/ruleset/rules.py:114
+#: peekaboo/ruleset/rules.py:116
#, python-format
msgid "File is more than %d bytes long"
msgstr "Datei ist nur %d bytes lang"
-#: peekaboo/ruleset/rules.py:133
+#: peekaboo/ruleset/rules.py:135
msgid "File type is on whitelist"
msgstr "Dateityp ist auf Whitelist"
-#: peekaboo/ruleset/rules.py:137
+#: peekaboo/ruleset/rules.py:139
msgid "File type is not on whitelist"
msgstr "Dateityp ist nicht auf Whitelist"
-#: peekaboo/ruleset/rules.py:156
+#: peekaboo/ruleset/rules.py:158
msgid "File type is on the list of types to analyze"
msgstr "Dateityp ist auf der Liste der zu analysiserenden Typen"
-#: peekaboo/ruleset/rules.py:161
+#: peekaboo/ruleset/rules.py:163
#, python-format
msgid "File type is not on the list of types to analyse (%s)"
msgstr "Dateityp ist nicht auf der Liste der zu analysierenden Typen (%s)"
-#: peekaboo/ruleset/rules.py:174
+#: peekaboo/ruleset/rules.py:176
msgid "The file contains an Office macro"
msgstr "Die Datei beinhaltet ein Office-Makro"
-#: peekaboo/ruleset/rules.py:178
+#: peekaboo/ruleset/rules.py:180
msgid "The file does not contain a recognizable Office macro"
msgstr "Die Datei beinhaltet kein erkennbares Office-Makro"
-#: peekaboo/ruleset/rules.py:205 peekaboo/ruleset/rules.py:327
+#: peekaboo/ruleset/rules.py:210 peekaboo/ruleset/rules.py:332
msgid ""
"Behavioral analysis by Cuckoo has produced an error and did not finish "
"successfully"
@@ -161,49 +156,48 @@ msgstr ""
"Die Verhaltensanalyse durch Cuckoo hat einen Fehler produziert und konnte"
" nicht erfolgreich abgeschlossen werden"
-#: peekaboo/ruleset/rules.py:239
+#: peekaboo/ruleset/rules.py:244
msgid "Empty list of malicious signatures"
msgstr "Leere Liste schädlicher Signaturen"
-#: peekaboo/ruleset/rules.py:257
+#: peekaboo/ruleset/rules.py:262
msgid "No signature suggesting malware detected"
msgstr "Keine Signatur erkannt die auf Schadcode hindeutet"
-#: peekaboo/ruleset/rules.py:262
+#: peekaboo/ruleset/rules.py:267
#, python-format
msgid "The following signatures have been recognized: %s"
msgstr "Folgende Signaturen wurden erkannt: %s"
-#: peekaboo/ruleset/rules.py:279
+#: peekaboo/ruleset/rules.py:284
#, python-format
msgid "Cuckoo score >= %s: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:284
+#: peekaboo/ruleset/rules.py:289
#, python-format
msgid "Cuckoo score < %s: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:300
+#: peekaboo/ruleset/rules.py:305
msgid "Empty domain list"
msgstr "Leere Domainliste"
-#: peekaboo/ruleset/rules.py:305
+#: peekaboo/ruleset/rules.py:310
#, python-format
msgid "The file attempts to contact at least one domain on the blacklist (%s)"
msgstr ""
"Die Datei versucht mindestens eine Domain aus der Blacklist zu "
"kontaktieren (%s)"
-#: peekaboo/ruleset/rules.py:311
+#: peekaboo/ruleset/rules.py:316
msgid "File does not seem to attempt contact with domains on the blacklist"
msgstr "Datei scheint keine Domains aus der Blacklist kontaktieren zu wollen"
-#: peekaboo/ruleset/rules.py:347
+#: peekaboo/ruleset/rules.py:352
msgid "Behavioral analysis by Cuckoo completed successfully"
msgstr "Die Verhaltensanalyse durch Cuckoo wurde erfolgreich abgeschlossen"
-#: peekaboo/ruleset/rules.py:364
+#: peekaboo/ruleset/rules.py:369
msgid "File does not seem to exhibit recognizable malicious behaviour"
msgstr "Datei scheint keine erkennbaren Schadroutinen zu starten"
-
diff --git a/peekaboo/locale/peekaboo.pot b/peekaboo/locale/peekaboo.pot
index 8551395..d2231b7 100644
--- a/peekaboo/locale/peekaboo.pot
+++ b/peekaboo/locale/peekaboo.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2019-04-15 15:41+0000\n"
+"POT-Creation-Date: 2019-04-17 09:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,188 +17,183 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.4.0\n"
-#: peekaboo/queuing.py:390
+#: peekaboo/queuing.py:382
msgid "Sample initialization failed"
msgstr ""
-#: peekaboo/sample.py:189
+#: peekaboo/sample.py:186
#, python-format
msgid "File \"%s\" %s is being analyzed"
msgstr ""
-#: peekaboo/sample.py:242
+#: peekaboo/sample.py:239
#, python-format
msgid "File \"%s\" is considered \"%s\""
msgstr ""
-#: peekaboo/sample.py:302
+#: peekaboo/sample.py:299
#, python-format
msgid "File \"%s\": %s"
msgstr ""
-#: peekaboo/sample.py:498
+#: peekaboo/sample.py:495
#, python-format
msgid "Sample %s successfully submitted to Cuckoo as job %d"
msgstr ""
-#: peekaboo/server.py:143
+#: peekaboo/server.py:141
msgid "Hello, this is Peekaboo."
msgstr ""
-#: peekaboo/server.py:176
+#: peekaboo/server.py:174
msgid "Error: Invalid JSON in request."
msgstr ""
-#: peekaboo/server.py:181
+#: peekaboo/server.py:179
msgid "ERROR: Invalid data structure."
msgstr ""
-#: peekaboo/server.py:188
+#: peekaboo/server.py:186
msgid "ERROR: Incomplete data structure."
msgstr ""
-#: peekaboo/server.py:195
+#: peekaboo/server.py:193
msgid "ERROR: Path does not exist or no permission to access it."
msgstr ""
-#: peekaboo/server.py:202
+#: peekaboo/server.py:200
msgid "ERRROR: Input is not a file"
msgstr ""
-#: peekaboo/server.py:209
+#: peekaboo/server.py:207
msgid "Error submitting sample to job queue"
msgstr ""
-#: peekaboo/server.py:241
+#: peekaboo/server.py:239
msgid "Files are being analyzed..."
msgstr ""
-#: peekaboo/server.py:264
+#: peekaboo/server.py:262
msgid "Peekaboo is shutting down."
msgstr ""
-#: peekaboo/server.py:316
+#: peekaboo/server.py:314
#, python-format
msgid "The file collection has been categorized \"%s\""
msgstr ""
-#: peekaboo/ruleset/__init__.py:66
+#: peekaboo/ruleset/__init__.py:64
msgid "Rule without result"
msgstr ""
-#: peekaboo/ruleset/__init__.py:70
+#: peekaboo/ruleset/__init__.py:68
#, python-format
msgid "Result \"%s\" of rule %s - %s, analysis continues: %s."
msgstr ""
-#: peekaboo/ruleset/__init__.py:72
+#: peekaboo/ruleset/__init__.py:70
msgid "Yes"
msgstr ""
-#: peekaboo/ruleset/__init__.py:72
+#: peekaboo/ruleset/__init__.py:70
msgid "No"
msgstr ""
-#: peekaboo/ruleset/engine.py:88
-#, python-format
-msgid "Rule '%s' is disabled."
-msgstr ""
-
-#: peekaboo/ruleset/engine.py:102
+#: peekaboo/ruleset/engine.py:97
msgid "Rule aborted with error"
msgstr ""
-#: peekaboo/ruleset/rules.py:84
+#: peekaboo/ruleset/rules.py:86
msgid "File is not yet known to the system"
msgstr ""
-#: peekaboo/ruleset/rules.py:104
+#: peekaboo/ruleset/rules.py:106
#, python-format
msgid "Failure to determine sample file size: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:109
+#: peekaboo/ruleset/rules.py:111
#, python-format
msgid "File has more than %d bytes"
msgstr ""
-#: peekaboo/ruleset/rules.py:114
+#: peekaboo/ruleset/rules.py:116
#, python-format
msgid "File is more than %d bytes long"
msgstr ""
-#: peekaboo/ruleset/rules.py:133
+#: peekaboo/ruleset/rules.py:135
msgid "File type is on whitelist"
msgstr ""
-#: peekaboo/ruleset/rules.py:137
+#: peekaboo/ruleset/rules.py:139
msgid "File type is not on whitelist"
msgstr ""
-#: peekaboo/ruleset/rules.py:156
+#: peekaboo/ruleset/rules.py:158
msgid "File type is on the list of types to analyze"
msgstr ""
-#: peekaboo/ruleset/rules.py:161
+#: peekaboo/ruleset/rules.py:163
#, python-format
msgid "File type is not on the list of types to analyse (%s)"
msgstr ""
-#: peekaboo/ruleset/rules.py:174
+#: peekaboo/ruleset/rules.py:176
msgid "The file contains an Office macro"
msgstr ""
-#: peekaboo/ruleset/rules.py:178
+#: peekaboo/ruleset/rules.py:180
msgid "The file does not contain a recognizable Office macro"
msgstr ""
-#: peekaboo/ruleset/rules.py:205 peekaboo/ruleset/rules.py:327
+#: peekaboo/ruleset/rules.py:210 peekaboo/ruleset/rules.py:332
msgid ""
"Behavioral analysis by Cuckoo has produced an error and did not finish "
"successfully"
msgstr ""
-#: peekaboo/ruleset/rules.py:239
+#: peekaboo/ruleset/rules.py:244
msgid "Empty list of malicious signatures"
msgstr ""
-#: peekaboo/ruleset/rules.py:257
+#: peekaboo/ruleset/rules.py:262
msgid "No signature suggesting malware detected"
msgstr ""
-#: peekaboo/ruleset/rules.py:262
+#: peekaboo/ruleset/rules.py:267
#, python-format
msgid "The following signatures have been recognized: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:279
+#: peekaboo/ruleset/rules.py:284
#, python-format
msgid "Cuckoo score >= %s: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:284
+#: peekaboo/ruleset/rules.py:289
#, python-format
msgid "Cuckoo score < %s: %s"
msgstr ""
-#: peekaboo/ruleset/rules.py:300
+#: peekaboo/ruleset/rules.py:305
msgid "Empty domain list"
msgstr ""
-#: peekaboo/ruleset/rules.py:305
+#: peekaboo/ruleset/rules.py:310
#, python-format
msgid "The file attempts to contact at least one domain on the blacklist (%s)"
msgstr ""
-#: peekaboo/ruleset/rules.py:311
+#: peekaboo/ruleset/rules.py:316
msgid "File does not seem to attempt contact with domains on the blacklist"
msgstr ""
-#: peekaboo/ruleset/rules.py:347
+#: peekaboo/ruleset/rules.py:352
msgid "Behavioral analysis by Cuckoo completed successfully"
msgstr ""
-#: peekaboo/ruleset/rules.py:364
+#: peekaboo/ruleset/rules.py:369
msgid "File does not seem to exhibit recognizable malicious behaviour"
msgstr ""
diff --git a/peekaboo/ruleset/engine.py b/peekaboo/ruleset/engine.py
index 8b4287b..86b95e8 100644
--- a/peekaboo/ruleset/engine.py
+++ b/peekaboo/ruleset/engine.py
@@ -40,7 +40,7 @@ class RulesetEngine(object):
@since: 1.6
"""
- rules = [
+ known_rules = [
KnownRule,
FileLargerThanRule,
FileTypeOnWhitelistRule,
@@ -59,9 +59,14 @@ class RulesetEngine(object):
self.config = ruleset_config
self.db_con = db_con
+ # create a lookup table from rule name to class
+ self.rules = {}
+ for known_rule in self.known_rules:
+ self.rules[known_rule.rule_name] = known_rule
+
def run(self):
- for rule in RulesetEngine.rules:
- result = self.__exec_rule(self.sample, rule)
+ for rule in self.config.rule_config('rules').get('rule'):
+ result = self.__exec_rule(self.sample, self.rules[rule])
if not result.further_analysis:
return
@@ -75,18 +80,9 @@ class RulesetEngine(object):
logger.debug("Processing rule '%s' for %s" % (rule_name, sample))
try:
- # skip disabled rules.
- if self.config.rule_enabled(rule_name):
- rule_config = self.config.rule_config(rule_name)
- rule = rule_class(config=rule_config, db_con=self.db_con)
- result = rule.evaluate(sample)
- else:
- logger.debug("Rule '%s' is disabled." % rule_name)
- result = RuleResult(
- rule_name, result=Result.unchecked,
- reason=_("Rule '%s' is disabled.") % rule_name,
- further_analysis=True)
-
+ rule_config = self.config.rule_config(rule_name)
+ rule = rule_class(config=rule_config, db_con=self.db_con)
+ result = rule.evaluate(sample)
sample.add_rule_result(result)
except PeekabooAnalysisDeferred:
# in case the Sample is requesting the Cuckoo report
diff --git a/peekaboo/ruleset/rules.py b/peekaboo/ruleset/rules.py
index 120e4f5..a631cc1 100644
--- a/peekaboo/ruleset/rules.py
+++ b/peekaboo/ruleset/rules.py
@@ -40,6 +40,8 @@ class Rule(object):
""" This is the base class for all rules. It provides common infrastructure
such as resources that can be used by the rules (configuration, database
connection) or helper functions. """
+ rule_name = 'unimplemented'
+
def __init__(self, config=None, db_con=None):
""" Initialize common configuration and resources """
self.db_con = db_con
diff --git a/ruleset.conf.sample b/ruleset.conf.sample
index cde5f5b..c8909a9 100644
--- a/ruleset.conf.sample
+++ b/ruleset.conf.sample
@@ -2,15 +2,23 @@
# Peekaboo ruleset configuration file
# Copyright (C) 2016-2019 science + computing ag
#
-# rule specific configuration options
-# the section name equals the name of the rule
-#
-
-[known]
-# if not specified the default is enabled : yes
-enabled : yes
+# list of rules to run on samples
+[rules]
+rule.1 : known
+rule.2 : file_larger_than
+rule.3 : file_type_on_whitelist
+rule.4 : file_type_on_greylist
+rule.5 : cuckoo_evil_sig
+rule.6 : cuckoo_score
+rule.7 : office_macro
+#rule.8 : requests_evil_domain
+rule.9 : cuckoo_analysis_failed
+#rule.10 : contains_peekabooyar
+rule.11 : final_rule
+# rule specific configuration options
+# the section name equals the name of the rule
#[file_larger_than]
# defaults:
#bytes : 5
@@ -113,15 +121,10 @@ signature.43 : Wscript.exe initiated network communications indicative of a scri
#higher_than : 4.0
[requests_evil_domain]
-enabled : no
# define a list of bad domains here
domain.1 : canarytokens.com
-# this rule is for testing only, so it is disabled by default
-[contains_peekabooyar]
-enabled : no
-
-[cuckoo_analysis_failed]
+#[cuckoo_analysis_failed]
# This rule checks whether analysis by Cuckoo failed. If so, it reports a
# result of "failed" for this sample and aborts rule processing. In case of
# success, result "unknown" is returned (because successful analysis in itself
@@ -153,5 +156,7 @@ enabled : no
#failure.1: end of analysis reached!
# rules without configuration options:
+# - known
+# - contains_peekabooyar
# - office_macro
# - final_rule