예제 #1
0
        def check_value(term):
            if term is None:
                return False

            if isinstance(term, list):
                return any(check_value(t) for t in term)

            if isinstance(term, (bool, float, int)) or utils.is_string(term):
                v = value

                if utils.is_string(v) and isinstance(term, (bool, int, float)):
                    if isinstance(v, bool):
                        v = v == "false"
                    if isinstance(term, int):
                        v = int(v)
                    elif isinstance(v, float):
                        v = float(v)

                elif utils.is_string(term) and isinstance(
                        v, (bool, int, float)):
                    v = utils.to_unicode(v)

                return compare_function(term, v)
            else:
                raise KqlRuntimeError("Cannot compare value {}".format(term))
예제 #2
0
def _parse(text,
           start=None,
           preprocessor=None,
           implied_any=False,
           implied_base=False,
           pipes=True,
           subqueries=True):
    """Function for parsing EQL with arbitrary entry points.

    :param str text: EQL source text to parse
    :param str start: Entry point for the EQL grammar
    :param bool implied_any: Allow for event queries to match on any event type when a type is not specified.
         If enabled, the query ``process_name == "cmd.exe"`` becomes ``any where process_name == "cmd.exe"``
    :param bool implied_base: Allow for queries to be built with only pipes. Base query becomes 'any where true'
    :param bool pipes: Toggle support for pipes
    :param bool subqueries: Toggle support for subqueries, which are required by
        ``sequence``, ``join``, ``descendant of``, ``child of`` and ``event of``
    :param PreProcessor preprocessor: Optional preprocessor to expand definitions and constants
    :rtype: EqlNode
    """
    global GRAMMAR, tatsu_parser

    if tatsu_parser is None:
        GRAMMAR = get_etc_file('eql.ebnf')
        tatsu_parser = tatsu.compile(
            GRAMMAR,
            parseinfo=True,
            semantics=tatsu.semantics.ModelBuilderSemantics())

    if not text.strip():
        raise ParseError("No text specified", 0, 0, text)

    # Convert everything to unicode
    text = to_unicode(text)
    walker = EqlWalker(implied_any=implied_any,
                       implied_base=implied_base,
                       preprocessor=preprocessor,
                       pipes=pipes,
                       subqueries=subqueries)

    try:
        model = tatsu_parser.parse(text,
                                   rule_name=start,
                                   start=start,
                                   parseinfo=True)
        eql_node = walker.walk(model)
        return eql_node
    except tatsu.exceptions.FailedParse as e:
        info = e.buf.line_info(e.pos)
        message = e.message
        line = info.line
        col = info.col
        source = info.text.rstrip()
        if not source:
            source = text.strip().splitlines()[-1].strip()
            col = max(len(source) - 1, 0)
        raise ParseError(message, line, col, source)
예제 #3
0
 def _error(node, message, end=False, cls=ParseError):
     """Callback function to walk the AST."""
     params = dict(node.ast)
     for k, value in params.items():
         if isinstance(value, list):
             params[k] = ', '.join([
                 v.render() if isinstance(v, EqlNode) else to_unicode(v)
                 for v in value
             ])
     message = message.format(**params)
     lines = node.parseinfo.text_lines()
     line_number = node.parseinfo.line
     if line_number >= len(lines):
         line_number = len(lines) - 1
     bad_line = lines[line_number].rstrip()
     pos = node.parseinfo.endpos if end else node.parseinfo.pos
     return cls(message, line_number, pos, bad_line)
예제 #4
0
 def walk__literal(self, node):
     """Callback function to walk the AST."""
     literal = self.walk(node.value)
     if literal is None:
         return literal
     elif is_string(literal):
         # If a 'raw' string is detected, then only unescape the quote character
         if node.text.startswith('?'):
             quote_char = node.text[-1]
             literal = literal.replace("\\" + quote_char, quote_char)
         else:
             literal = String.unescape(literal)
         return String(to_unicode(literal))
     elif isinstance(literal, bool):
         return Boolean(literal)
     else:
         return Number(literal)
예제 #5
0
    def _test_interactive_shell(self):
        """Test that commands can be executed via the interactive shell."""
        class Arguments(object):
            config = None
            file = None

        actual_stdin = io.StringIO(
            to_unicode("\n".join([
                "input %s" % EVENTS_FILE,
                "table process_path parent_process_path",
                "search\nprocess where serial_event_id in (32, 33);",
            ])))

        expected_stdout_text = "\n".join([
            BANNER,
            "eql> input %s" % EVENTS_FILE,
            "Using file %s with %d events" %
            (EVENTS_FILE, len(TestEngine.get_events())),
            "eql> table process_path parent_process_path",
            "eql> search process where serial_event_id in (32, 33)",
            Table([[
                "C:\\Windows\\System32\\sppsvc.exe",
                "C:\\Windows\\System32\\services.exe"
            ],
                   [
                       "C:\\Windows\\System32\\dwm.exe",
                       "C:\\Windows\\System32\\svchost.exe"
                   ]],
                  names=["process_path", "parent_process_path"]).__unicode__()
        ])

        actual_stdout = []

        # Now actually run with redirected stdout and stdin
        with mock.patch('sys.stdin', new=actual_stdin):
            shell_main(Arguments())

        actual_stdout_lines = "\n".join(actual_stdout).splitlines()
        self.assertListEqual(actual_stdout_lines,
                             expected_stdout_text.splitlines())
예제 #6
0
 def _concat(*args):
     return u"".join(to_unicode(arg) for arg in args)
예제 #7
0
파일: ast.py 프로젝트: sgnls/eql
 def _render(self):
     return to_unicode(self.value)