Skip to main content

Parse YARA rules

Project description

plyara

PyPi Version

Parse YARA rules into a dictionary representation.

Plyara is a script and library that lexes and parses a file consisting of one more YARA rules into a python dictionary representation. The goal of this tool is to make it easier to perform bulk operations or transformations of large sets of YARA rules, such as extracting indicators, updating attributes, and analyzing a corpus. Other applications include linters and dependency checkers.

Plyara leverages the Python module PLY for lexing YARA rules.

This is a community-maintained fork of the original plyara by 8u1a. The "plyara" trademark is used with permission.

Installation

Plyara requires Python 3.10+.

Install with pip:

pip install plyara

Usage

Use the plyara Python library in your own applications:

>>> import plyara
>>> parser = plyara.Plyara()
>>> mylist = parser.parse_string('rule MyRule { strings: $a="1" \n condition: false }')
>>>
>>> import pprint
>>> pprint.pprint(mylist)
[{'condition_terms': ['false'],
  'raw_condition': 'condition: false ',
  'raw_strings': 'strings: $a="1" \n ',
  'rule_name': 'MyRule',
  'start_line': 1,
  'stop_line': 2,
  'strings': [{'name': '$a', 'type': 'text', 'value': '1'}]}]
>>>

Or, use the included plyara script from the command line:

$ plyara -h
usage: plyara [-h] [--log] FILE

Parse YARA rules into a dictionary representation.

positional arguments:
  FILE        File containing YARA rules to parse.

optional arguments:
  -h, --help  show this help message and exit
  --log       Enable debug logging to the console.

The command-line tool will print valid JSON output when parsing rules:

$ cat example.yar
rule silent_banker : banker
{
    meta:
        description = "This is just an example"
        thread_level = 3
        in_the_wild = true
    strings:
        $a = {6A 40 68 00 30 00 00 6A 14 8D 91}
        $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}
        $c = "UVODFRYSIHLNWPEJXQZAKCBGMT"
    condition:
        $a or $b or $c
}
$ plyara example.yar
[
    {
        "condition_terms": [
            "$a",
            "or",
            "$b",
            "or",
            "$c"
        ],
        "metadata": [
            {
                "description": "This is just an example"
            },
            {
                "thread_level": 3
            },
            {
                "in_the_wild": true
            }
        ],
        "raw_condition": "condition:\n        $a or $b or $c\n",
        "raw_meta": "meta:\n        description = \"This is just an example\"\n        thread_level = 3\n        in_the_wild = true\n    ",
        "raw_strings": "strings:\n        $a = {6A 40 68 00 30 00 00 6A 14 8D 91}\n        $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}\n        $c = \"UVODFRYSIHLNWPEJXQZAKCBGMT\"\n    ",
        "rule_name": "silent_banker",
        "start_line": 1,
        "stop_line": 13,
        "strings": [
            {
                "name": "$a",
                "type": "byte",
                "value": "{6A 40 68 00 30 00 00 6A 14 8D 91}"
            },
            {
                "name": "$b",
                "type": "byte",
                "value": "{8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}"
            },
            {
                "name": "$c",
                "type": "text",
                "value": "UVODFRYSIHLNWPEJXQZAKCBGMT"
            }
        ],
        "tags": [
            "banker"
        ]
    }
]

Reusing The Parser

If you want to reuse a single instance of the parser object for efficiency when parsing large quantities of rule or rulesets, the new clear() method must be used.

rules = list()
parser = plyara.Plyara()

for file in files:
    with open(file, 'r') as fh:
        yararules = parser.parse_string(fh.read())
        rules += yararules
    parser.clear()

Breaking Change: Import Effects

Background

Imports are available to be used in a rule even if not used in a condition. Also, any module which is imported at all is used in processing all files scanned using the ruleset regardless if the import is used anywhere. Some users require that all rules affected by a particular import include that import in the dictionary output of plyara. At the same time, many users expect that a particular rule not include an import if that import is not used in the rule.

New Parameter: Import Effects

A new class constructor parameter called import_effects has been added to the parser. This parameter defaults to False which is a breaking change. Users who wish to retain the behavior from versions before 2.2, will need to set this parameter to True like so:

parser = plyara.Plyara(import_effects=True)

Note

When reusing a parser for multiple rules and/or files and import_effects is enabled, be aware that imports are now shared across all rules - if one rule has an import, that import will be added to all rules in your parser object.

Known Issues

Due to an unsolved issue with precendece, a - operator is being considered a negative number. Until this is fixed, it is recommended that users employ YARA-X's fmt command to pre-process yara rulesets for automatic formatting before using plyara on problematic rulesets.

yr fmt foo.yar

More information here: https://github.com/plyara/plyara/issues/112

Contributing

  • If you find a bug, or would like to see a new feature, Pull Requests and Issues are always welcome.
  • By submitting changes, you agree to release those changes under the terms of the LICENSE.
  • Writing passing unit tests for your changes, while not required, is highly encouraged and appreciated.
  • Please run all code contributions through each of the linters that we use for this project:
    • pycodestyle
    • pydocstyle
    • pyflakes
  • For more information on these linters, please refer to the Python Code Quality Authority

Unit Tests

python -m unittest discover

Coverage

coverage run -m unittest discover
coverage report -m

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

plyara-2.2.2.tar.gz (35.2 kB view details)

Uploaded Source

Built Distribution

plyara-2.2.2-py3-none-any.whl (24.2 kB view details)

Uploaded Python 3

File details

Details for the file plyara-2.2.2.tar.gz.

File metadata

  • Download URL: plyara-2.2.2.tar.gz
  • Upload date:
  • Size: 35.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.13.1

File hashes

Hashes for plyara-2.2.2.tar.gz
Algorithm Hash digest
SHA256 008c57b6ef4873437c236f70da1fec3f911d5acb1c996cdaf56921572be54acd
MD5 3e3fe1c32746116ec764a71a0b69d415
BLAKE2b-256 2d53ebd0ea7227c2c51fc685b921e106874e7664c1232fa116397c2300fa96df

See more details on using hashes here.

File details

Details for the file plyara-2.2.2-py3-none-any.whl.

File metadata

  • Download URL: plyara-2.2.2-py3-none-any.whl
  • Upload date:
  • Size: 24.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.13.1

File hashes

Hashes for plyara-2.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8776cae3018dcc99e3cceadf9a267f6facf11b38320b30356aab731f8087f12f
MD5 0fff16dd1d171bd42afe057c06e99876
BLAKE2b-256 fc469b0d7836056c7404fc88444d701d0b9a5488395aaaed135b836c0c2a5f27

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page