def ValidateSyntax(self): """Validates artifact syntax. This method can be used to validate individual artifacts as they are loaded, without needing all artifacts to be loaded first, as for Validate(). Raises: ArtifactSyntaxError: If artifact syntax is invalid. """ if not self.doc: raise ArtifactSyntaxError(self, "missing doc") for supp_os in self.supported_os: valid_os = self.SUPPORTED_OS_LIST if supp_os not in valid_os: detail = "invalid `supported_os` ('%s' not in %s)" % (supp_os, valid_os) raise ArtifactSyntaxError(self, detail) for condition in self.conditions: # FIXME(hanuszczak): It does not look like the code below can throw # `ConditionException`. Do we really need it then? try: of = objectfilter.Parser(condition).Parse() of.Compile(objectfilter.BaseFilterImplementation) except ConditionError as e: detail = "invalid condition '%s'" % condition raise ArtifactSyntaxError(self, detail, e) for label in self.labels: if label not in self.ARTIFACT_LABELS: raise ArtifactSyntaxError(self, "invalid label '%s'" % label) # Anything listed in provides must be defined in the KnowledgeBase valid_provides = rdf_client.KnowledgeBase().GetKbFieldNames() for kb_var in self.provides: if kb_var not in valid_provides: detail = "broken `provides` ('%s' not in %s)" % ( kb_var, valid_provides) raise ArtifactSyntaxError(self, detail) # Any %%blah%% path dependencies must be defined in the KnowledgeBase for dep in self.GetArtifactPathDependencies(): if dep not in valid_provides: detail = "broken path dependencies ('%s' not in %s)" % ( dep, valid_provides) raise ArtifactSyntaxError(self, detail) for source in self.sources: try: source.Validate() except ArtifactSourceSyntaxError as e: raise ArtifactSyntaxError(self, "bad source", e)
def ValidateSyntax(self): """Validate artifact syntax. This method can be used to validate individual artifacts as they are loaded, without needing all artifacts to be loaded first, as for Validate(). Raises: ArtifactDefinitionError: If artifact is invalid. """ cls_name = self.name if not self.doc: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has missing doc" % cls_name) for supp_os in self.supported_os: if supp_os not in artifact_lib.SUPPORTED_OS_LIST: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has invalid supported_os %s" % (cls_name, supp_os)) for condition in self.conditions: try: of = objectfilter.Parser(condition).Parse() of.Compile(objectfilter.BaseFilterImplementation) except artifact_lib.ConditionError as e: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has invalid condition %s. %s" % (cls_name, condition, e)) for label in self.labels: if label not in artifact_lib.ARTIFACT_LABELS: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has an invalid label %s. Please use one from " "ARTIFACT_LABELS." % (cls_name, label)) for kb_var in self.provides: if len(kb_var) < 3: # Someone probably interpreted string as list. raise artifact_lib.ArtifactDefinitionError( "Artifact %s has broken provides. %s" % (cls_name, self.provides)) for collector in self.collectors: try: collector.Validate() except artifact_lib.Error as e: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has bad collector. %s" % (cls_name, e))
def CheckCondition(condition, check_object): """Check if a condition matches an object. Args: condition: A string condition e.g. "os == 'Windows'" check_object: Object to validate, e.g. an rdf_client.KnowledgeBase() Returns: True or False depending on whether the condition matches. Raises: ConditionError: If condition is bad. """ try: of = objectfilter.Parser(condition).Parse() compiled_filter = of.Compile(objectfilter.BaseFilterImplementation) return compiled_filter.Matches(check_object) except objectfilter.Error as e: raise ConditionError(e)
def testCompile(self): obj = DummyObject("something", "Blue") parser = objectfilter.Parser("something == 'Blue'").Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), True) parser = objectfilter.Parser("something == 'Red'").Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), False) parser = objectfilter.Parser("something == \"Red\"").Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), False) obj = DummyObject("size", 4) parser = objectfilter.Parser("size < 3").Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), False) parser = objectfilter.Parser("size == 4").Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), True) query = "something is 'Blue' and size notcontains 3" parser = objectfilter.Parser(query).Parse() filter_ = parser.Compile(self.filter_imp) self.assertEqual(filter_.Matches(obj), False)
def _Compile(self, expression): try: of = objectfilter.Parser(expression).Parse() return of.Compile(objectfilter.LowercaseAttributeFilterImplementation) except objectfilter.Error as e: raise DefinitionError(e)
def testParse(self): # Arguments are either int, float or quoted string objectfilter.Parser("attribute == 1").Parse() objectfilter.Parser("attribute == 0x10").Parse() parser = objectfilter.Parser("attribute == 1a") self.assertRaises(objectfilter.ParseError, parser.Parse) objectfilter.Parser("attribute == 1.2").Parse() objectfilter.Parser("attribute == 'bla'").Parse() objectfilter.Parser("attribute == \"bla\"").Parse() parser = objectfilter.Parser("something == red") self.assertRaises(objectfilter.ParseError, parser.Parse) # Can't start with AND parser = objectfilter.Parser("and something is 'Blue'") self.assertRaises(objectfilter.ParseError, parser.Parse) # Need to close braces objectfilter.Parser("(a is 3)").Parse() parser = objectfilter.Parser("(a is 3") self.assertRaises(objectfilter.ParseError, parser.Parse) # Need to open braces to close them parser = objectfilter.Parser("a is 3)") self.assertRaises(objectfilter.ParseError, parser.Parse) # Context Operator alone is not accepted parser = objectfilter.Parser("@attributes") self.assertRaises(objectfilter.ParseError, parser.Parse) # Accepted only with braces objectfilter.Parser("@attributes( name is 'adrien')").Parse() # Not without them parser = objectfilter.Parser("@attributes name is 'adrien'") self.assertRaises(objectfilter.ParseError, parser.Parse) # Can nest context operators query = "@imported_dlls( @imported_function( name is 'OpenFileA'))" objectfilter.Parser(query).Parse() # Can nest context operators and mix braces without it messing up query = "@imported_dlls( @imported_function( name is 'OpenFileA'))" parser = objectfilter.Parser(query).Parse() query = """ @imported_dlls ( @imported_function ( name is 'OpenFileA' and ordinal == 12 ) ) """ parser = objectfilter.Parser(query).Parse() # Mix context and binary operators query = """ @imported_dlls ( @imported_function ( name is 'OpenFileA' ) AND num_functions == 2 ) """ parser = objectfilter.Parser(query).Parse() # Also on the right query = """
def testContext(self): self.assertRaises(objectfilter.InvalidNumberOfOperands, objectfilter.Context, arguments=["context"], value_expander=self.value_expander) self.assertRaises( objectfilter.InvalidNumberOfOperands, objectfilter.Context, arguments=[ "context", objectfilter.Equals(arguments=["path", "value"], value_expander=self.value_expander), objectfilter.Equals(arguments=["another_path", "value"], value_expander=self.value_expander) ], value_expander=self.value_expander) # "One imported_dll imports 2 functions AND one imported_dll imports # function RegQueryValueEx" arguments = [ objectfilter.Equals(["imported_dlls.num_imported_functions", 1], value_expander=self.value_expander), objectfilter.Contains( ["imported_dlls.imported_functions", "RegQueryValueEx"], value_expander=self.value_expander) ] condition = objectfilter.AndFilter(arguments=arguments) # Without context, it matches because both filters match separately self.assertEqual(True, condition.Matches(self.file)) arguments = [ objectfilter.Equals(["num_imported_functions", 2], value_expander=self.value_expander), objectfilter.Contains(["imported_functions", "RegQueryValueEx"], value_expander=self.value_expander) ] condition = objectfilter.AndFilter(arguments=arguments) # "The same DLL imports 2 functions AND one of these is RegQueryValueEx" context = objectfilter.Context(arguments=["imported_dlls", condition], value_expander=self.value_expander) # With context, it doesn't match because both don't match in the same dll self.assertEqual(False, context.Matches(self.file)) # "One imported_dll imports only 1 function AND one imported_dll imports # function RegQueryValueEx" condition = objectfilter.AndFilter(arguments=[ objectfilter.Equals(arguments=["num_imported_functions", 1], value_expander=self.value_expander), objectfilter.Contains(["imported_functions", "RegQueryValueEx"], value_expander=self.value_expander) ]) # "The same DLL imports 1 function AND it"s RegQueryValueEx" context = objectfilter.Context(["imported_dlls", condition], value_expander=self.value_expander) self.assertEqual(True, context.Matches(self.file)) # Now test the context with a straight query query = """ @imported_dlls ( imported_functions contains "RegQueryValueEx" AND num_imported_functions == 1 ) """ filter_ = objectfilter.Parser(query).Parse() filter_ = filter_.Compile(self.filter_imp) self.assertEqual(True, filter_.Matches(self.file))
def Validate(self): """Attempt to validate the artifact has been well defined. This is used to enforce Artifact rules. Raises: ArtifactDefinitionError: If artifact is invalid. """ cls_name = self.name if not self.doc: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has missing doc" % cls_name) for supp_os in self.supported_os: if supp_os not in artifact_lib.SUPPORTED_OS_LIST: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has invalid supported_os %s" % (cls_name, supp_os)) for condition in self.conditions: try: of = objectfilter.Parser(condition).Parse() of.Compile(objectfilter.BaseFilterImplementation) except artifact_lib.ConditionError as e: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has invalid condition %s. %s" % (cls_name, condition, e)) for label in self.labels: if label not in artifact_lib.ARTIFACT_LABELS: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has an invalid label %s. Please use one from " "ARTIFACT_LABELS." % (cls_name, label)) # Check all path dependencies exist in the knowledge base. valid_fields = rdfvalue.KnowledgeBase().GetKbFieldNames() for dependency in self.GetArtifactPathDependencies(): if dependency not in valid_fields: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has an invalid path dependency %s. Artifacts must use " "defined knowledge attributes." % (cls_name, dependency)) # Check all artifact dependencies exist. for dependency in self.GetArtifactDependencies(): if dependency not in artifact_lib.ArtifactRegistry.artifacts: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has an invalid dependency %s . Could not find artifact" " definition." % (cls_name, dependency)) for collector in self.collectors: try: collector.Validate() except artifact_lib.Error as e: raise artifact_lib.ArtifactDefinitionError( "Artifact %s has bad collector. %s" % (cls_name, e)) for kb_var in self.provides: if len(kb_var) < 3: # Someone probably interpreted string as list. raise artifact_lib.ArtifactDefinitionError( "Artifact %s has broken provides. %s" % (cls_name, self.provides))