Beispiel #1
0
    def test_empty_string(self):

        inputTags = r'''

    rule thirteen
    {
    meta:
    my_identifier_1 = ""
    my_identifier_2 = 24
    my_identifier_3 = true

    strings:
        $my_text_string = "text here"
        $my_hex_string = { E2 34 A1 C8 23 FB }

    condition:
        $my_text_string or $my_hex_string
    }

    '''

        interp.ParserInterpreter.rules = []
        result = interp.parseString(inputTags, isPrintDebug=False)

        for rule in result:
            rule_name = rule["rule_name"]
            if rule_name == 'thirteen':
                self.assertTrue(len(rule['metadata']) == 3)
Beispiel #2
0
  def test_empty_string(self):

    inputTags = r'''

    rule thirteen
    {
    meta:
    my_identifier_1 = ""
    my_identifier_2 = 24
    my_identifier_3 = true

    strings:
        $my_text_string = "text here"
        $my_hex_string = { E2 34 A1 C8 23 FB }

    condition:
        $my_text_string or $my_hex_string
    }

    '''

    interp.ParserInterpreter.rules = []
    result = interp.parseString(inputTags, isPrintDebug=False)

    for rule in result:
      rule_name = rule["rule_name"]
      if rule_name == 'thirteen':
        self.assertTrue(len(rule['metadata']) == 3 )
Beispiel #3
0
    def test_rule_name_imports_and_scopes(self):

        inputStringNIS = r'''

    rule four {meta: i = "j" strings: $a = "b" condition: true }

    global rule five {meta: i = "j" strings: $a = "b" condition: false }

    private rule six {meta: i = "j" strings: $a = "b" condition: true }

    global private rule seven {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    rule eight {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    import "lib2"
    rule nine {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    import "lib2"
    private global rule ten {meta: i = "j" strings: $a = "b" condition: true }

    '''

        interp.ParserInterpreter.rules = []
        result = interp.parseString(inputStringNIS, isPrintDebug=False)

        self.assertEqual(len(result), 7)

        for rule in result:
            rule_name = rule["rule_name"]
            if rule_name == 'four':
                self.assertTrue('scopes' not in rule)
                self.assertTrue('imports' not in rule)
            if rule_name == 'five':
                self.assertTrue('imports' not in rule)
                self.assertTrue('global' in rule['scopes'])
            if rule_name == 'six':
                self.assertTrue('imports' not in rule)
                self.assertTrue('private' in rule['scopes'])
            if rule_name == 'seven':
                self.assertTrue('imports' not in rule)
                self.assertTrue('private' in rule['scopes']
                                and 'global' in rule['scopes'])
            if rule_name == 'eight':
                self.assertTrue('"lib1"' in rule['imports'])
                self.assertTrue('scopes' not in rule)
            if rule_name == 'nine':
                self.assertTrue('"lib1"' in rule['imports']
                                and '"lib2"' in rule['imports'])
                self.assertTrue('scopes' not in rule)
            if rule_name == 'ten':
                self.assertTrue('"lib1"' in rule['imports']
                                and '"lib2"' in rule['imports'])
                self.assertTrue('global' in rule['scopes']
                                and 'private' in rule['scopes'])
Beispiel #4
0
  def test_rule_name_imports_and_scopes(self):

    inputStringNIS = r'''

    rule four {meta: i = "j" strings: $a = "b" condition: true }

    global rule five {meta: i = "j" strings: $a = "b" condition: false }

    private rule six {meta: i = "j" strings: $a = "b" condition: true }

    global private rule seven {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    rule eight {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    import "lib2"
    rule nine {meta: i = "j" strings: $a = "b" condition: true }

    import "lib1"
    import "lib2"
    private global rule ten {meta: i = "j" strings: $a = "b" condition: true }

    '''

    interp.ParserInterpreter.rules = []
    result = interp.parseString(inputStringNIS, isPrintDebug=False)

    self.assertEqual(len(result), 7)

    for rule in result:
      rule_name = rule["rule_name"]
      if rule_name == 'four':
        self.assertTrue('scopes' not in rule)
        self.assertTrue('imports' not in rule)
      if rule_name == 'five':
        self.assertTrue('imports' not in rule)
        self.assertTrue('global' in rule['scopes'])
      if rule_name == 'six':
        self.assertTrue('imports' not in rule)
        self.assertTrue('private' in rule['scopes'])
      if rule_name == 'seven':
        self.assertTrue('imports' not in rule)
        self.assertTrue('private' in rule['scopes'] and 'global' in rule['scopes'])
      if rule_name == 'eight':
        self.assertTrue('"lib1"' in rule['imports'])
        self.assertTrue('scopes' not in rule)
      if rule_name == 'nine':
        self.assertTrue('"lib1"' in rule['imports'] and '"lib2"' in rule['imports'])
        self.assertTrue('scopes' not in rule)
      if rule_name == 'ten':
        self.assertTrue('"lib1"' in rule['imports'] and '"lib2"' in rule['imports'])
        self.assertTrue('global' in rule['scopes'] and 'private' in rule['scopes'])
Beispiel #5
0
  def test_tags(self):

    inputTags = r'''

    rule eleven: tag1 {meta: i = "j" strings: $a = "b" condition: true }

    rule twelve : tag1 tag2 {meta: i = "j" strings: $a = "b" condition: true }

    '''

    result = interp.parseString(inputTags, isPrintDebug=False)

    for rule in result:
      rule_name = rule["rule_name"]
      if rule_name == 'eleven':
        self.assertTrue(len(rule['tags']) == 1 and 'tag1' in rule['tags'])
      if rule_name == 'twelve':
        self.assertTrue(len(rule['tags']) == 2 and
                        'tag1' in rule['tags'] and 'tag2' in rule['tags'])
Beispiel #6
0
def query_by_hash(qhash):
    yara = redis.get('query:' + qhash)

    try:
        rules = interp.parseString(yara)
    except Exception as e:
        return error_page(yara, 'PLYara failed (not my fault): ' + str(e))

    if len(rules) > 1:
        return error_page(yara, 'More than one rule specified')

    rule_name = rules[0].get('rule_name')

    try:
        parser = YaraParser(rules[0])
        pre_parsed = parser.pre_parse()
        parsed = parser.parse()
    except Exception as e:
        return error_page(yara, 'YaraParser failed (msm\'s fault): ' + str(e))

    matches = redis.smembers('matches:' + qhash)
    false_positives = redis.smembers('false_positives:' + qhash)
    job = redis.hgetall('job:' + qhash)
    debug = 'debug' in request.args

    error = job.get('error')

    body = render_template('index.html',
                           yara=yara,
                           pre_parsed=pre_parsed,
                           parsed=parsed,
                           job=job,
                           matches=matches,
                           errors=error,
                           false_positives=false_positives,
                           debug=debug,
                           saved_rules=get_saved_rules(),
                           qhash=qhash,
                           rule_name=rule_name,
                           repo_url=config.REPO_URL)

    return body
Beispiel #7
0
def query_by_hash(qhash):
    yara = redis.get('query:' + qhash)

    try:
        rules = interp.parseString(yara)
    except Exception as e:
        return error_page(yara, 'PLYara failed (not my fault): ' + str(e))

    if len(rules) > 1:
        return error_page(yara, 'More than one rule specified')

    rule_name = rules[0].get('rule_name')

    try:
        parser = YaraParser(rules[0])
        pre_parsed = parser.pre_parse()
        parsed = parser.parse()
    except Exception as e:
        return error_page(yara, 'YaraParser failed (msm\'s fault): ' + str(e))

    matches = redis.smembers('matches:' + qhash)
    false_positives = redis.smembers('false_positives:' + qhash)
    job = redis.hgetall('job:' + qhash)
    debug = 'debug' in request.args

    error = job.get('error')

    body = render_template('index.html',
                           yara=yara,
                           pre_parsed=pre_parsed,
                           parsed=parsed,
                           job=job,
                           matches=matches,
                           errors=error,
                           false_positives=false_positives,
                           debug=debug,
                           saved_rules=get_saved_rules(),
                           qhash=qhash,
                           rule_name=rule_name,
                           repo_url=config.REPO_URL)

    return body
Beispiel #8
0
    def test_multiple_rules(self):

        inputString = r'''

    rule FirstRule {
      meta:
        author = "Andrés Iniesta"
        date = "2015-01-01"
      strings:
        $a = "hark, a \"string\" here" fullword ascii
        $b = { 00 22 44 66 88 aa cc ee }
      condition:
        all of them
      }

    import "bingo"
    import "bango"
    rule SecondRule : aTag {
      meta:
        author = "Ivan Rakitić"
        date = "2015-02-01"
      strings:
        $x = "hi"
        $y = /state: (on|off)/ wide
        $z = "bye"
      condition:
        for all of them : ( # > 2 )
    }

    rule ThirdRule {condition: uint32(0) == 0xE011CFD0}
    '''

        interp.ParserInterpreter.rules = []
        result = interp.parseString(inputString, isPrintDebug=False)

        self.assertEqual(len(result), 3)
        self.assertEqual(result[0]['metadata']['author'], '"Andrés Iniesta"')
        self.assertEqual(result[0]['metadata']['date'], '"2015-01-01"')
        self.assertTrue([x["name"]
                         for x in result[0]['strings']] == ['$a', '$b'])
Beispiel #9
0
  def test_multiple_rules(self):

    inputString = r'''

    rule FirstRule {
      meta:
        author = "Andrés Iniesta"
        date = "2015-01-01"
      strings:
        $a = "hark, a \"string\" here" fullword ascii
        $b = { 00 22 44 66 88 aa cc ee }
      condition:
        all of them
      }

    import "bingo"
    import "bango"
    rule SecondRule : aTag {
      meta:
        author = "Ivan Rakitić"
        date = "2015-02-01"
      strings:
        $x = "hi"
        $y = /state: (on|off)/ wide
        $z = "bye"
      condition:
        for all of them : ( # > 2 )
    }

    rule ThirdRule {condition: uint32(0) == 0xE011CFD0}
    '''

    interp.ParserInterpreter.rules = []
    result = interp.parseString(inputString, isPrintDebug=False)

    self.assertEqual(len(result), 3)
    self.assertEqual(result[0]['metadata']['author'], '"Andrés Iniesta"')
    self.assertEqual(result[0]['metadata']['date'], '"2015-01-01"')
    self.assertTrue([x["name"] for x in result[0]['strings']] == ['$a','$b'])
Beispiel #10
0
    def test_tags(self):

        inputTags = r'''

    rule eleven: tag1 {meta: i = "j" strings: $a = "b" condition: true }

    rule twelve : tag1 tag2 {meta: i = "j" strings: $a = "b" condition: true }

    '''

        interp.ParserInterpreter.rules = []
        result = interp.parseString(inputTags, isPrintDebug=False)

        for rule in result:
            rule_name = rule["rule_name"]
            if rule_name == 'eleven':
                self.assertTrue(
                    len(rule['tags']) == 1 and 'tag1' in rule['tags'])
            if rule_name == 'twelve':
                self.assertTrue(
                    len(rule['tags']) == 2 and 'tag1' in rule['tags']
                    and 'tag2' in rule['tags'])
Beispiel #11
0
#!/usr/bin/env python
#-*- coding: utf-8 -*-

import operator
import os
import sys

sys.path.insert(0, os.getcwd())
import plyara.interp as interp

# Plyara is a script that lexes and parses a file consisting of one more Yara
# rules into a python dictionary representation.
if __name__ == '__main__':
    file_to_analyze = sys.argv[1]
    rulesDict = interp.parseString(open(file_to_analyze).read())
    authors = {}
    imps = {}
    meta_keys = {}
    max_strings = []
    max_string_len = 0
    tags = {}
    rule_count = 0

    for rule in rulesDict:
        rule_count += 1

    # Imports
    if 'imports' in rule:
        for imp in rule['imports']:
            imp = imp.replace('"', '')
Beispiel #12
0
import operator
import os
import sys

sys.path.insert(0, os.getcwd())
import plyara.interp as interp


if __name__ == '__main__':

  file_to_analyze = sys.argv[1]

  print("...parsing file...")
  rulesDict = interp.parseString(open(file_to_analyze).read())
  print("...analyzing dictionary...")

  authors = {}
  imps = {}
  meta_keys = {}
  max_strings = []
  max_string_len = 0
  tags = {}
  rule_count = 0

  for rule in rulesDict:
    rule_count += 1

    #Imports
    if 'imports' in rule:
      for imp in rule['imports']:
        imp = imp.replace('"','')
Beispiel #13
0
def execute_job(job_id, hash, yara_rule):
    logging.info('Parsing...')

    redis.hmset(job_id, {
        'status': 'processing',
        'timestamp': time.time(),
    })

    try:
        rules = interp.parseString(yara_rule)
        parser = YaraParser(rules[0])
        parsed = parser.parse()
    except Exception as e:
        logging.exception(e)
        raise RuntimeError('Failed to parse Yara')

    redis.hmset(job_id, {
        'status': 'querying',
        'timestamp': time.time(),
    })

    logging.info('Querying backend...')
    result = db.query(parsed)
    if 'error' in result:
        raise RuntimeError(result['error'])

    job = redis.hgetall(job_id)
    files = [f for f in result['files'] if f.strip()]

    logging.info('Database responded with {} files'.format(len(files)))

    if 'max_files' in job and int(job['max_files']) > 0:
        files = files[:int(job['max_files'])]

    redis.hmset(job_id, {
        'total_files': len(files),
        'files_processed': 0,
    })

    logging.info('Compiling Yara')
    try:
        rule = yara.compile(source=yara_rule)
    except SyntaxError as e:
        logging.exception('Yara parse error')
        raise e

    for file_ndx, file_path in enumerate(files):
        matches = rule.match(data=open(file_path, 'rb').read())
        if matches:
            logging.info('Processed (match): {}'.format(file_path))
            redis.sadd('matches:' + hash, file_path)
        else:
            logging.info('Processed (nope ): {}'.format(file_path))
            redis.sadd('false_positives:' + hash, file_path)

        redis.hmset(job_id, {
            'files_processed': file_ndx + 1,
        })

        status = redis.hget(job_id, 'status')
        if status == 'cancelled':
            logging.info('Job cancelled')
            return

    redis.hmset(job_id, {
        'status': 'done',
    })
    logging.info('Done')