Ejemplo n.º 1
0
 def p_xor_mod_args(self, p):
     '''xor_mod_args : LPAREN NUM RPAREN
                      | LPAREN NUM HYPHEN NUM RPAREN
                      | LPAREN HEXNUM RPAREN
                      | LPAREN HEXNUM HYPHEN HEXNUM RPAREN
                      | LPAREN NUM HYPHEN HEXNUM RPAREN
                      | LPAREN HEXNUM HYPHEN NUM RPAREN'''
     logger.debug('Matched an xor arg: {}'.format(''.join(p[1:])))
     mods = [x for x in p if x not in (None, '(', '-', ')')]
     mod_int_list = []
     mod_lineidx = set()
     for i, x in enumerate(mods):
         mod_int = int(x, 16) if x.startswith('0x') else int(x)
         if 0 <= mod_int <= 255:
             mod_int_list.append(mod_int)
             mod_lineidx.add(i)
         else:
             message = 'String modification value {} not between 0-255 on line {}'.format(
                 x, p.lineno(1 + i))
             raise ParseTypeError(message, p.lineno, p.lexpos)
     if mod_int_list[0] > mod_int_list[-1]:
         mod_lineno = list({p.lineno(1 + i) for i in mod_lineidx})
         mod_lineno.sort()
         line_no = ' and '.join(str(lno) for lno in mod_lineno)
         message = 'String modification lower bound exceeds upper bound on line {}'.format(
             line_no)
         raise ParseTypeError(message, p.lineno, p.lexpos)
     else:
         mod_str_mod = YaraXor(mod_int_list)
         logger.debug('Matched string modifier(s): {}'.format(mod_str_mod))
         self._add_element(ElementTypes.STRINGS_MODIFIER, mod_str_mod)
Ejemplo n.º 2
0
 def _add_string_modifier(self, p):
     mod_str = p[1]
     prev_mod_with_args = False
     if mod_str in self.string_modifiers:
         message = 'Duplicate string modifier {} on line {}'.format(mod_str, p.lineno(1))
         raise ParseTypeError(message, p.lineno, p.lexpos)
     if mod_str in self.EXCLUSIVE_TEXT_MODIFIERS:
         prev_mods = {x for x in self.string_modifiers if isinstance(x, str)}
         excluded_modifiers = prev_mods & ({mod_str} ^ self.EXCLUSIVE_TEXT_MODIFIERS)
         if excluded_modifiers:
             prev_mod_str = excluded_modifiers.pop()
             message = ('Mutually exclusive string modifier use of {} on line {} after {} usage'
                        .format(mod_str, p.lineno(1), prev_mod_str))
             raise ParseTypeError(message, p.lineno, p.lexpos)
     if self.string_modifiers:
         # Convert previously created modifiers with args to strings
         if mod_str.startswith('base64') and isinstance(self.string_modifiers[-1], YaraBase64):
             if mod_str == 'base64wide':
                 self.string_modifiers[-1].modifier_name = 'base64wide'
                 logger.debug('Corrected base64 string modifier to base64wide')
             self.string_modifiers[-1] = str(self.string_modifiers[-1])
             prev_mod_with_args = True
         elif mod_str == 'xor' and isinstance(self.string_modifiers[-1], YaraXor):
             self.string_modifiers[-1] = str(self.string_modifiers[-1])
             logger.debug('Modified xor string was already added')
             prev_mod_with_args = True
     if not prev_mod_with_args:
         self._add_element(ElementTypes.STRINGS_MODIFIER, mod_str)
         logger.debug('Matched a string modifier: {}'.format(mod_str))
Ejemplo n.º 3
0
 def _process_string_with_escapes(t, escape_chars=None):
     if escape_chars is None:
         escape_chars = [t.value]
     if t.lexer.escape == 1 and t.value in escape_chars or t.value == '\\':
         t.lexer.escape ^= 1
         if t.value == 'x':
             t.lexer.hex_escape = 2
     elif t.lexer.hex_escape > 0:
         if t.value.lower() in string.hexdigits:
             t.lexer.hex_escape -= 1
         else:
             raise ParseTypeError('Invalid hex character: {!r}, at line: {}'.format(t.value, t.lexer.lineno),
                                  t.lexer.lineno, t.lexer.lexpos)
     elif t.lexer.escape == 1:
         raise ParseTypeError('Invalid escape sequence: \\{}, at line: {}'.format(t.value, t.lexer.lineno),
                              t.lexer.lineno, t.lexer.lexpos)
Ejemplo n.º 4
0
    def t_error(t):
        """Raise parsing error.

        Args:
            t: Token input from lexer.

        Raises:
            ParseTypeError
        """
        raise ParseTypeError('Illegal character {!r} at line {}'.format(t.value[0], t.lexer.lineno),
                             t.lexer.lineno, t.lexer.lexpos)
Ejemplo n.º 5
0
    def t_REXSTRING_error(t):
        """Raise parsing error for illegal rexstring character.

        Args:
            t: Token input from lexer.

        Raises:
            ParseTypeError
        """
        raise ParseTypeError('Illegal rexstring character : {!r}, at line: {}'.format(t.value[0], t.lexer.lineno),
                             t.lexer.lineno, t.lexer.lexpos)
Ejemplo n.º 6
0
    def p_rule(self, p):
        '''rule : scopes RULE ID tag_section LBRACE rule_body RBRACE'''
        logger.info('Matched rule: {}'.format(p[3]))
        if '.' in p[3]:
            message = 'Invalid rule name {}, on line {}'.format(p[3], p.lineno(1))
            raise ParseTypeError(message, p.lineno, p.lexpos)
        logger.debug('Rule start: {}, Rule stop: {}'.format(p.lineno(2), p.lineno(7)))

        while self._rule_comments:
            comment = self._rule_comments.pop()

            if p.lexpos(5) < comment.lexpos < p.lexpos(7):
                self._add_element(getattr(ElementTypes, comment.type), comment.value)

        element_value = (p[3], int(p.lineno(2)), int(p.lineno(7)), )
        self._add_element(ElementTypes.RULE_NAME, element_value)
Ejemplo n.º 7
0
    def _parse_string_kv(self, p, string_type):
        """Perform parsing for all string types.

        Args:
            p: Parser object.
            string_type: StringTypes enum.
        """
        key = p[1]
        value = p[3]
        match = re.match('"(.+)"', value)
        if match:
            value = match.group(1)
        if key != '$' and key in self._stringnames:
            message = 'Duplicate string name key {} on line {}'.format(key, p.lineno(1))
            raise ParseTypeError(message, p.lineno, p.lexpos)
        self._stringnames.add(key)
        logger.debug('Matched strings kv: {} equals {}'.format(key, value))
        self._add_element(ElementTypes.STRINGS_KEY_VALUE, (key, value, string_type, ))
Ejemplo n.º 8
0
    def p_error(self, p):
        """Raise syntax errors.

        Args:
            p: Data from the parser.

        Raises:
            ParseTypeError
        """
        if not p:
            # This happens when we try to parse an empty string or file, or one with no actual rules.
            pass
        elif p.type in ('COMMENT', 'MCOMMENT'):
            self.parser.errok()  # This is a method from PLY to reset the error state from parsing a comment
            self._rule_comments.append(p)
        else:
            message = 'Unknown text {} for token of type {} on line {}'.format(p.value, p.type, p.lineno)
            raise ParseTypeError(message, p.lineno, p.lexpos)