以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:代表待扫描的文件或者文件夹
返回结果格式:规则名 文件名(中间以空格隔开)
- 第三方库(项目中使用此方法):
简单介绍使用过程(不同语言可能会有所不同):
- 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规则文件更新到服务器上,然后重新编译规则文件即可。