使用python调用yara进行文件检测

以linux-centos7系统为例,无论是命令行使用yara还是第三方组件使用yara都必须先安装yara的执行环境。

1、yara说明

Yara 是一个识别和分类恶意文件的工具,其安装的环境依赖比较多,安装前先执行yum update,然后在用yum install直接装automake、 libtool、 make、gcc、pkg-config环境。Yara安装软件到官网Getting started — yara 4.4.0 documentation下载并根据官网说明进行安装,我本地的版本为4.4.0。

2、检查Yara是否安装成功

查看yara的版本来验证安装:yara -v 或者 yara --version

  

3、使用方法

Yara有两种使用方式:

  • 命令行方式:

yara /path/rules1.yar /path/rules2.yar /path/to/scan

/path/rules1.yar /path/rules2.yar:代表规则文件,多个以空格分割

/path/to/scan:代表待扫描的文件或者文件夹

返回结果格式:规则名 文件名(中间以空格隔开)

  • 第三方库(项目中使用此方法):

简单介绍使用过程(不同语言可能会有所不同):

  1. demo使用流程

python封装yara使用代码

import base64
import os
import yara
import logging

from yara import Error

class YaraManager(object):
    """ doc """

    categories = {}

    def __init__(self):
        self.rules_path = os.path.join(HOME_ROOT, "data", "rules")

    @staticmethod
    def __get_categories(path):
        try:
            return [di for di in os.listdir(path) if os.path.isdir(os.path.join(path, di))]
        except OSError as os_error:
            logging.warning("Please install sandbox-rules package to make yara detection normal. Exception:{0}"
                            .format(os_error))
            return []

    def _generate_default_rules(self):
        log.debug("Initializing Yara Rules...")

        # Need to define each external variable that will be used in the
        # future. Otherwise Yara will complain.
        externals = {
            'filename': "",
            'filepath': "",
            'extension': "",
            'filetype': "",
            'md5': ""
        }

        for category in self.__get_categories(self.rules_path):
            basepath = os.path.join(self.rules_path, category)
            if not os.path.exists(basepath):
                log.warning("Missing Yara directory: %s?", basepath)

            rules, indexed = {}, []
            for dirpath, dirnames, filenames in os.walk(basepath, followlinks=True):
                for filename in filenames:
                    if not filename.endswith((".yar", ".yara")):
                        continue

                    filepath = os.path.join(dirpath, filename)

                    try:
                      assert len(str(filepath)) == len(filepath)
                    except (UnicodeEncodeError, AssertionError):
                        log.warning(
                            "Can't load Yara rules at %r as Unicode filepaths are "
                            "currently not supported in combination with Yara!",
                            filepath
                        )
                        continue

                    try:
                        yara.compile(filepath=filepath, externals=externals)
                    except yara.SyntaxError as e:
                        log.warning("Error compiling the rules {0}".format(e))
                        continue

                    rules["rule_%s_%d" % (category, len(rules))] = filepath

            try:
                YaraManager.categories[category] = yara.compile(filepaths=rules, externals=externals)
            except yara.Error as e:
                log.warning(
                    "There was a syntax error in one or more Yara rules: %s" % e
                )
                continue

            # The memory.py processing module requires a yara file with all of its
            # rules embedded in it, so create this file to remain compatible.
                 for filename in indexed:
                    f.write('include "%s"\n' % filename)

            # indexed = sorted(indexed)
            # for entry in indexed:
            #     if entry == indexed[-1]:
            #         log.debug("\t `-- %s %s", category, entry)
            #     else:
            #         log.debug("\t |-- %s %s", category, entry)

            # Store the compiled Yara rules for the "memory" category in $CWD/stuff/
            # so that we may easily pass it along to zer0m0n during an analysis.
      

    def generate_index(self):
        """Generates index for yara signatures."""
        self._generate_default_rules()

    @staticmethod
    def yara_match(externals, results):
        try:
            if isinstance(externals["filepath"], unicode):
                externals["filepath"] = externals.get("filepath").encode("utf8")
            if isinstance(externals["filename"], unicode):
                externals["filename"] = externals.get("filename").encode("utf8")

            for item, rules in YaraManager.categories.items():
                match_rules = []

                matches = rules.match(externals["filepath"], externals=externals, timeout=5)
                for match in matches:
                    # skip duplicate rule
                    if item in results and any([x for x in results[item] if match.rule == x.get("name", "")]):
                        # if match.rule in self.rule_names:
                        continue
                    # else:
                    #     self.rule_names.append(match.rule)

                    strings, offsets = set(), {}
                    for _, key, value in match.strings:
                        strings.add(base64.b64encode(value))
                        offsets[key.lstrip("$")] = []

                    strings = sorted(strings)
                    for offset, key, value in match.strings:
                        offsets[key.lstrip("$")].append(
                            (offset, strings.index(base64.b64encode(value)))
                        )

                    meta = {
                        "description": "(no description)",
                    }
                    meta.update(match.meta)

                    match_rules.append({
                        "name": match.rule,
                        "tags": match.tags,
                        "meta": meta,
                        "strings": strings,
                        "offsets": offsets,
                    })

                if match_rules:
                    results[item] = results[item] + match_rules if item in results else match_rules
        except Error as e:
            log.info("Unable to match {0} Heuristic signatures: {1}".format(item, e))
        except Exception as e:
            log.exception(e)

        return results

方法调用

    def run(self):
        """Get Yara signatures matches.
        @return: matched Yara signatures.
        """
        results = {}
        for item, rules in YaraManager.categories.items():
            match_rules = []
            try:
                matches = rules.match(self.task.target, timeout=5)
                for match in matches:
                    match_rules.append({
                        "name": match.rule
                    })
            except Error as e:
                log.info("Unable to match {0} Heuristic signatures: {1}".format(item, e))

            if match_rules:
                results[item] = match_rules

        return results

4、更新病毒库

将最新的yara规则文件更新到服务器上,然后重新编译规则文件即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心编码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值