YARA规则编写Skill yara-rule-authoring

这个技能用于编写高质量的YARA-X检测规则来识别恶意软件,包括命名约定、字符串选择、性能优化、从旧版YARA迁移、减少误报等。适用于安全研究人员、恶意软件分析师和网络安全工程师。关键词:YARA-X, 恶意软件检测, 规则编写, 网络安全, 威胁狩猎, IOC, 签名, crx模块, dex模块。

安全运维 0 次安装 0 次浏览 更新于 3/14/2026

名称: yara-规则编写 描述: > 指导编写高质量的YARA-X检测规则用于恶意软件识别。 当编写、审查或优化YARA规则时使用。涵盖命名约定、字符串选择、性能优化、从旧版YARA迁移、减少误报。触发词: YARA, YARA-X, 恶意软件检测, 威胁狩猎, IOC, 签名, crx模块, dex模块。

YARA-X规则编写

编写检测规则以捕获恶意软件而不陷入误报泛滥。

此技能针对YARA-X,基于Rust的旧版YARA的后继者。YARA-X驱动VirusTotal的生产系统,是推荐实现。如果您有现有规则,请参见从旧版YARA迁移

核心原则

  1. 字符串必须生成良好的原子 — YARA提取4字节子序列以进行快速匹配。具有重复字节、常见序列或少于4字节的字符串会迫使在太多文件上执行缓慢的字节码验证。

  2. 针对特定家族,而非类别 — “检测勒索软件” 什么都抓不到。“检测LockBit 3.0配置提取例程” 捕获您想要的内容。

  3. 部署前测试对抗良性软件 — 在Windows系统文件上触发的规则是无用的。使用VirusTotal的良性软件语料库或您自己的清洁文件集进行验证。

  4. 首先使用廉价检查短路 — 将 filesize < 10MB and uint16(0) == 0x5A4D 放在昂贵的字符串搜索或模块调用之前。

  5. 元数据是文档 — 未来的您(和您的团队)需要知道这捕获了什么、为什么以及样本来自何处。

何时使用

  • 为恶意软件检测编写新的YARA-X规则
  • 审查现有规则的质量或性能问题
  • 优化运行缓慢的规则集
  • 将IOC或威胁情报转换为检测签名
  • 调试误报问题
  • 准备规则用于生产部署
  • 将旧版YARA规则迁移到YARA-X
  • 分析Chrome扩展(crx模块)
  • 分析Android应用(dex模块)

何时不使用

  • 需要反汇编的静态分析 → 使用Ghidra/IDA技能
  • 动态恶意软件分析 → 使用沙箱分析技能
  • 基于网络的检测 → 使用Suricata/Snort技能
  • 使用Volatility的内存取证 → 使用内存取证技能
  • 简单的基于哈希的检测 → 仅使用哈希列表

YARA-X概述

YARA-X是基于Rust的旧版YARA的后继者:5-10倍更快的正则表达式、更好的错误、内置格式化器、更严格的验证、新模块(crx, dex)、99%规则兼容性。

安装: brew install yara-x (macOS) 或 cargo install yara-x

基本命令: yr scan, yr check, yr fmt, yr dump

平台考虑

YARA适用于任何文件类型。根据目标调整模式:

平台 魔数字节 不良字符串 良好字符串
Windows PE uint16(0) == 0x5A4D API名称, Windows路径 互斥锁名称, PDB路径
macOS Mach-O uint32(0) == 0xFEEDFACE (32位), 0xFEEDFACF (64位), 0xCAFEBABE (通用) 常见Obj-C方法 键盘记录器字符串, 持久化路径
JavaScript/Node (不需要) require, fetch, axios 混淆器签名, eval+解码链
npm/pip包 (不需要) postinstall, dependencies 可疑包名, 渗出URL
Office文档 uint32(0) == 0x504B0304 VBA关键词 宏自动执行, 编码载荷
VS Code扩展 (不需要) vscode.workspace 不常见的activationEvents, 隐藏文件访问
Chrome扩展 使用 crx 模块 常见Chrome API 权限滥用, 清单异常
Android应用 使用 dex 模块 标准DEX结构 混淆类, 可疑权限

macOS恶意软件检测

尚无专用Mach-O模块。使用魔数字节检查 + 字符串模式:

魔数字节:

// Mach-O 32位
uint32(0) == 0xFEEDFACE
// Mach-O 64位
uint32(0) == 0xFEEDFACF
// 通用二进制 (胖二进制)
uint32(0) == 0xCAFEBABE or uint32(0) == 0xBEBAFECA

macOS恶意软件的良好指标:

  • 键盘记录器痕迹: CGEventTapCreate, kCGEventKeyDown
  • SSH隧道字符串: ssh -D, tunnel, socks
  • 持久化路径: ~/Library/LaunchAgents, /Library/LaunchDaemons
  • 凭据盗窃: security find-generic-password, keychain

来自Airbnb BinaryAlert的示例模式:

规则 SUSP_Mac_ProtonRAT
{
    字符串:
        // 库指标
        $lib1 = "SRWebSocket" ascii
        $lib2 = "SocketRocket" ascii

        // 行为指标
        $behav1 = "SSH tunnel not launched" ascii
        $behav2 = "Keylogger" ascii

    条件:
        (uint32(0) == 0xFEEDFACF or uint32(0) == 0xCAFEBABE) and
        any of ($lib*) and any of ($behav*)
}

JavaScript检测决策树

编写JavaScript规则?
├─ npm包?
│  ├─ 检查package.json模式
│  ├─ 查找postinstall/preinstall钩子
│  └─ 目标渗出模式: fetch + 环境访问 + 凭据路径
├─ 浏览器扩展?
│  ├─ Chrome: 使用crx模块
│  └─ 其他: 目标清单模式, 后台脚本行为
├─ 独立JS文件?
│  ├─ 查找混淆标记: eval+atob, fromCharCode链
│  ├─ 目标唯一函数/变量名(常存活于压缩)
│  └─ 检查打包/编码载荷
└─ 压缩/webpack捆绑包?
   ├─ 目标存活于捆绑的唯一字符串(URL, 魔术值)
   └─ 避免函数名(将被混淆)

JavaScript特定良好字符串:

  • Ethereum函数选择器: { 70 a0 82 31 } (transfer)
  • 零宽度字符(隐写术): { E2 80 8B E2 80 8C }
  • 混淆器签名: _0x, var _0x
  • 特定C2模式: 域名, webhook URL

JavaScript特定不良字符串:

  • require, fetch, axios — 太常见
  • Buffer, crypto — 到处有合法用途
  • process.env 单独 — 需要特定环境变量名

基本工具集

工具 用途
yarGen 提取候选字符串: yarGen.py -m samples/ --excludegood → 用 yr check 验证
FLOSS 提取混淆/栈字符串: floss sample.exe (当yarGen失败时)
yr CLI 验证: yr check, 扫描: yr scan -s, 检查: yr dump -m pe
signature-base 学习质量示例
YARA-CI 部署前良性软件语料库测试

掌握这五个。不要分心于工具目录。

拒绝的合理化

当您发现自己在想这些时,停止并重新考虑。

合理化 专家回应
“这个通用字符串足够独特” 首先测试对抗良性软件。您的直觉是错误的。
“yarGen给了我这些字符串” yarGen建议,您验证。手动检查每个。
“它在我的10个样本上有效” 10个样本 ≠ 生产。使用VirusTotal良性软件语料库。
“一个规则捕获所有变体” 导致误报泛滥。针对特定家族。
“如果收到误报,我会使其更具体” 从一开始编写严格的规则。误报破坏信任。
“这个十六进制模式是唯一的” 在一个样本中唯一 ≠ 在恶意软件生态系统中唯一。
“性能不重要” 一个慢规则减慢整个规则集。优化原子。
“PEiD规则仍然有效” 过时。32位打包器不相关。
“我会稍后添加更多条件” 弱规则部署 = 损害已造成。
“这只是用于狩猎” 狩猎规则成为检测规则。相同的质量标准。
“API名称使其恶意” 合法软件使用相同API。需要行为上下文。
“any of them 对于这些常见字符串没问题” 常见字符串 + any = 误报泛滥。仅对单独唯一的字符串使用 any of
“这个正则表达式足够具体” /fetch.*token/ 匹配所有授权代码。添加渗出目的地要求。
“JavaScript看起来干净” 攻击者用注入污染合法代码。检查eval+解码链。
“我会用 .* 增加灵活性” 无界正则表达式 = 性能灾难 + 内存爆炸。使用 .{0,30}
“我会到处用 --relaxed-re-syntax” 掩盖真实错误。修复正则表达式而不是隐藏问题。

决策树

这个字符串足够好吗?

这个字符串足够好吗?
├─ 少于4字节?
│  └─ 否 — 找更长字符串
├─ 包含重复字节 (0000, 9090)?
│  └─ 否 — 添加上下文
├─ 是API名称 (VirtualAlloc, CreateRemoteThread)?
│  └─ 否 — 使用调用点的十六进制模式代替
├─ 出现在Windows系统文件中?
│  └─ 否 — 太通用,找独特内容
├─ 是常见路径 (C:\Windows\, cmd.exe)?
│  └─ 否 — 找恶意软件特定路径
├─ 对此恶意软件家族唯一?
│  └─ 是 — 使用它
└─ 出现在其他恶意软件中?
   └─ 可能 — 结合家族特定标记

何时使用 “all of” vs “any of”

我应该要求所有字符串还是允许任何?
├─ 字符串各自对恶意软件唯一?
│  └─ any of them (每个单独可疑)
├─ 字符串常见但组合可疑?
│  └─ all of them (要求完整模式)
├─ 字符串有不同置信度?
│  └─ 分组: all of ($core_*) and any of ($variant_*)
└─ 看到许多误报?
   └─ 收紧: 切换 any → all, 添加更多必需字符串

生产教训: 使用 any of ($network_*) 且字符串包括 “fetch”, “axios”, “http” 的规则匹配几乎所有Web应用。切换到要求凭据路径 AND 网络调用 AND 渗出目的地消除了误报。

何时放弃规则方法

当以下情况时停止并转向:

  • yarGen只返回API名称和路径 → 参见当字符串失败,转向结构

  • 找不到3个唯一字符串 → 可能已打包。针对解压版本或检测打包器。

  • 规则匹配良性软件文件 → 字符串不够唯一。1-2个匹配 = 调查并收紧;3-5个匹配 = 找不同指标;6+匹配 = 重新开始。

  • 即使优化后性能仍糟糕 → 架构问题。拆分为多个聚焦规则或添加严格预过滤器。

  • 描述难写 → 规则太模糊。如果您无法解释它捕获什么,它捕获太多。

调试误报

误报调查流程:
│
├─ 1. 哪个字符串匹配?
│     运行: yr scan -s rule.yar false_positive.exe
│
├─ 2. 它在合法库中吗?
│     └─ 添加: not $fp_vendor_string 排除
│
├─ 3. 是常见开发模式吗?
│     └─ 找更具体指标,替换字符串
│
├─ 4. 多个通用字符串一起匹配吗?
│     └─ 收紧要求 all + 添加唯一标记
│
└─ 5. 恶意软件使用常见技术吗?
      └─ 针对恶意软件特定实现细节,而非技术

十六进制 vs 文本 vs 正则表达式

我应该使用什么字符串类型?
│
├─ 精确ASCII/Unicode文本?
│  └─ 文本: $s = "MutexName" ascii wide
│
├─ 特定字节序列?
│  └─ 十六进制: $h = { 4D 5A 90 00 }
│
├─ 有变化的字节序列?
│  └─ 带通配符的十六进制: { 4D 5A ?? ?? 50 45 }
│
├─ 有结构的模式(URL, 路径)?
│  └─ 有界正则表达式: /https:\/\/[a-z]{5,20}\.onion/
│
└─ 未知编码(XOR, base64)?
   └─ 带修饰符的文本: $s = "config" xor(0x00-0xFF)

样本是否打包?(首先检查)

在编写任何基于字符串的规则之前:

样本是否打包?
├─ 熵 > 7.0?
│  └─ 可能打包 — 首先找解压层
├─ 很少/无可读字符串?
│  └─ 可能打包 — 使用熵, PE结构, 或打包器签名
├─ 检测到UPX/MPRESS/自定义打包器?
│  └─ 针对解压载荷 OR 检测打包器本身
└─ 有可读字符串?
   └─ 继续基于字符串的检测

专家指导: 不要针对打包层编写规则。打包改变;载荷不变。

当字符串失败,转向结构

如果yarGen只返回API名称和通用路径:

字符串提取失败 — 现在怎么办?
├─ 高熵段?
│  └─ 在特定段上使用 math.entropy()
├─ 不寻常导入模式?
│  └─ 使用 pe.imphash() 用于导入哈希聚类
├─ 一致的PE结构异常?
│  └─ 目标段名, 大小, 特性
├─ 有元数据?
│  └─ 目标版本信息, 时间戳, 资源
└─ 没有独特内容?
   └─ 此样本可能无法单独用YARA检测

专家指导: “可以尝试使用其他文件属性,如元数据、熵、导入哈希或其他保持恒定的数据。” — Kaspersky Applied YARA Training

专家启发法

字符串选择: 互斥锁名称是黄金;C2路径白银;错误消息青铜。栈字符串几乎总是唯一。如果您需要 >6 个字符串,您过拟合了。

条件设计:filesize < 开始,然后魔数字节,然后字符串,然后模块。如果 >5 行,拆分为多个规则。

质量信号: yarGen输出需要80%过滤。匹配 <50% 变体的规则太窄;匹配良性软件的太宽。

修饰符纪律:

  • 永不投机使用 nocasewide — 仅当您有确认证据表明样本中大小写/编码变化时使用
  • nocase 加倍原子生成;wide 加倍字符串匹配 — 两者都有真实成本
  • “如果您没有明确理由使用这些修饰符,不要做” — Kaspersky Applied YARA

正则表达式锚定:

  • 没有4+字节文字子串的正则表达式 在每个文件偏移评估 — 灾难性性能
  • 总是锚定正则表达式到独特文字: /mshta\.exe http:\/\/.../ 而不是 /http:\/\/.../
  • 如果无法锚定,考虑使用带通配符的十六进制模式代替

循环纪律:

  • 总是用filesize限定循环: filesize < 100KB and for all i in (1..#a) : ...
  • 无界 #a 在大文件中可能数千 — 指数级减速

YARA-X提示: $_unused 抑制警告;private $s 从输出隐藏;yr check + yr fmt 在每次提交前。

何时使用模块 vs 字节检查

我应该使用模块还是原始字节?
├─ 需要imphash/rich header/authenticode?
│  └─ 使用PE模块 — 太复杂无法复制
├─ 只检查魔数字节或简单偏移?
│  └─ 使用uint16/uint32 — 更快, 无模块开销
├─ 检查段名/大小?
│  └─ PE模块更干净,但先添加魔数字节过滤器
├─ 检查Chrome扩展权限?
│  └─ 使用crx模块 — 字符串解析脆弱
└─ 检查LNK目标路径?
   └─ 使用lnk模块 — LNK格式复杂

专家指导: “避免魔法模块 — 使用显式十六进制检查代替” — Neo23x0。应用此原则:如果您能用uint32()做,不要加载模块。

YARA-X新特性

最近版本的关键添加:

  • 私有模式 (v1.3.0+): private $helper = "pattern" — 匹配但从输出隐藏
  • 警告抑制 (v1.4.0+): // suppress: slow_pattern 内联注释
  • 数字下划线 (v1.5.0+): filesize < 10_000_000 提高可读性
  • 内置格式化器: yr fmt rules/ 标准化格式
  • NDJSON输出: yr scan --output-format ndjson 用于工具

YARA-X工具工作流

YARA-X提供旧版YARA缺乏的诊断工具:

规则开发周期:

# 1. 编写初始规则
# 2. 用详细错误检查语法
yr check rule.yar

# 3. 一致格式化
yr fmt -w rule.yar

# 4. 转储模块输出以检查文件结构(无需虚拟规则)
yr dump -m pe sample.exe --output-format yaml

# 5. 用时间信息扫描
time yr scan -s rule.yar corpus/

何时使用 yr dump:

  • 调查可用PE/ELF/Mach-O字段
  • 调试为什么模块条件不匹配
  • 在编写规则前探索新模块(crx, lnk, dotnet)

YARA-X诊断优势: 错误消息包括精确源位置。如果 yr check 指向第15行,问题确实在第15行(不同于旧版YARA)。

Chrome扩展分析 (crx模块)

crx 模块启用恶意Chrome扩展的检测。需要YARA-X v1.5.0+(基本),v1.11.0+ 用于 permhash()

关键API: crx.is_crx, crx.permissions, crx.permhash()

红旗: nativeMessaging + downloads, debugger 权限, 在 <all_urls> 上的内容脚本

导入 "crx"

规则 SUSP_CRX_HighRiskPerms {
    条件:
        crx.is_crx and
        for any perm in crx.permissions : (perm == "debugger")
}

参见 crx-module.md 获取完整API参考、权限风险评估和示例规则。

Android DEX分析 (dex模块)

dex 模块启用Android恶意软件的检测。需要YARA-X v1.11.0+。与旧版YARA的dex模块不兼容 — API完全不同。

关键API: dex.is_dex, dex.contains_class(), dex.contains_method(), dex.contains_string()

红旗: 单字母类名(混淆), DexClassLoader 反射, 加密资产

导入 "dex"

规则 SUSP_DEX_DynamicLoading {
    条件:
        dex.is_dex and
        dex.contains_class("Ldalvik/system/DexClassLoader;")
}

参见 dex-module.md 获取完整API参考、混淆检测和示例规则。

从旧版YARA迁移

YARA-X有99%规则兼容性,但强制执行更严格验证。

快速迁移:

yr check --relaxed-re-syntax rules/  # 识别问题
# 修复每个问题,然后:
yr check rules/  # 验证无放松模式

常见修复:

问题 旧版 YARA-X修复
正则表达式中的文字 { /{/ /\{/
无效转义 \R 静默文字 \\RR
Base64字符串 任何长度 需要3+字符
负索引 @a[-1] @a[#a - 1]
重复修饰符 允许 移除重复

注意: 仅将 --relaxed-re-syntax 用作诊断工具。修复问题而非依赖放松模式。

快速参考

命名约定

{类别}_{平台}_{家族}_{变体}_{日期}

常见前缀: MAL_ (恶意软件), HKTL_ (黑客工具), WEBSHELL_, EXPL_, SUSP_ (可疑), GEN_ (通用)

平台: Win_, Lnx_, Mac_, Android_, CRX_

示例: MAL_Win_Emotet_Loader_Jan25

参见 style-guide.md 获取完整约定、元数据要求和命名示例。

必需元数据

每个规则需要: description (以"Detects"开头), author, reference, date

元数据:
    description = "通过独特互斥锁和C2路径检测示例恶意软件"
    author = "您的姓名 <email@example.com>"
    reference = "https://example.com/分析"
    date = "2025-01-29"

字符串选择

良好: 互斥锁名称, PDB路径, C2路径, 栈字符串, 配置标记 不良: API名称, 常见可执行文件, 格式说明符, 通用路径

参见 strings.md 获取完整决策树和示例。

条件模式

为短路排序条件:

  1. filesize < 10MB (瞬时)
  2. uint16(0) == 0x5A4D (近乎瞬时)
  3. 字符串匹配 (廉价)
  4. 模块检查 (昂贵)

参见 performance.md 获取详细优化模式。

工作流

  1. 收集样本 — 多个样本;单样本规则脆弱
  2. 提取候选yarGen -m samples/ --excludegood
  3. 验证质量 — 使用决策树;yarGen需要80%过滤
  4. 编写初始规则 — 遵循模板和适当元数据
  5. 整理和测试yr check, yr fmt, 整理脚本
  6. 良性软件验证 — VirusTotal语料库或本地清洁文件
  7. 部署 — 添加仓库并带完整元数据,监控误报

参见 testing.md 获取详细验证工作流和误报调查。

有关从样本收集到部署的全面分步指南,参见 rule-development.md

常见错误

错误 不良 良好
API名称作为指标 "VirtualAlloc" 调用点的十六进制模式 + 独特互斥锁
无界正则表达式 /https?:\/\/.*/ /https?:\/\/[a-z0-9]{8,12}\.onion/
缺少文件类型过滤器 pe.imports(...) 第一 uint16(0) == 0x5A4D and filesize < 10MB 第一
短字符串 "abc" (3字节) "abcdef" (4+字节)
未转义大括号 (YARA-X) /config{key}/ /config\{key\}/

性能优化

快速获胜:filesize 放第一,避免 nocase, 有界正则表达式 {1,100}, 偏好十六进制而非正则表达式。

红旗: 字符串 <4字节, 无界正则表达式 (.*), 没有文件类型过滤器的模块。

参见 performance.md 获取原子理论和优化细节。

参考文档

主题 文档
命名和元数据约定 style-guide.md
性能和原子优化 performance.md
字符串类型和判断 strings.md
测试和验证 testing.md
Chrome扩展模块 (crx) crx-module.md
Android DEX模块 (dex) dex-module.md

工作流

主题 文档
完整规则开发过程 rule-development.md

示例规则

examples/ 目录包含真实、归属的规则,演示最佳实践:

示例 演示 来源
MAL_Win_Remcos_Jan25.yar PE恶意软件: 分级字符串计数, 每个家族多个规则 Elastic Security
MAL_Mac_ProtonRAT_Jan25.yar macOS: Mach-O魔数字节, 多类别分组 Airbnb BinaryAlert
MAL_NPM_SupplyChain_Jan25.yar npm供应链: 真实攻击模式, ERC-20选择器 Stairwell Research
SUSP_JS_Obfuscation_Jan25.yar JavaScript: 混淆器检测, 密度基匹配 imp0rtp3, Nils Kuhnert
SUSP_CRX_SuspiciousPermissions.yar Chrome扩展: crx模块, 权限 Educational

脚本

uv run {baseDir}/scripts/yara_lint.py rule.yar      # 验证样式/元数据
uv run {baseDir}/scripts/atom_analyzer.py rule.yar  # 检查字符串质量

参见 README.md 获取详细脚本文档。

质量检查清单

在部署任何规则前:

  • [ ] 名称遵循 {类别}_{平台}_{家族}_{变体}_{日期} 格式
  • [ ] 描述以"Detects"开头并解释什么/如何
  • [ ] 所有必需元数据存在(作者, 参考, 日期)
  • [ ] 字符串独特(非API名称, 常见路径, 或格式字符串)
  • [ ] 所有字符串有4+字节并良好原子潜力
  • [ ] Base64修饰符仅用于3+字符字符串
  • [ ] 正则表达式模式有转义 { 和有效转义序列
  • [ ] 条件以廉价检查开始(filesize, 魔数字节)
  • [ ] 规则匹配所有目标样本
  • [ ] 规则在良性软件语料库上产生零匹配
  • [ ] yr check 通过无错误
  • [ ] yr fmt --check 通过(一致格式化)
  • [ ] 整理器通过无错误
  • [ ] 同行评审完成

资源

质量YARA规则仓库

从生产规则学习。这些仓库包含经过良好测试、适当归属的规则:

仓库 重点 维护者
Neo23x0/signature-base 17,000+ 生产规则, 多平台 Florian Roth
Elastic/protections-artifacts 1,000+ 端点测试规则 Elastic Security
reversinglabs/reversinglabs-yara-rules 威胁研究规则 ReversingLabs
imp0rtp3/js-yara-rules JavaScript/浏览器恶意软件 imp0rtp3
InQuest/awesome-yara 资源精选索引 InQuest

样式与性能指南

指南 目的
YARA Style Guide 命名约定, 元数据, 字符串前缀
YARA Performance Guidelines 原子优化, 正则表达式边界
Kaspersky Applied YARA Training 生产使用的专家技术

工具

工具 目的
yarGen 从样本提取候选字符串
FLOSS 提取混淆和栈字符串
YARA-CI 自动化良性软件测试
YaraDbg 基于Web的规则调试器

macOS特定资源

资源 目的
Apple XProtect 生产macOS规则在 /System/Library/CoreServices/XProtect.bundle/
objective-see macOS恶意软件研究和样本
macOS Security Tools 参考列表

多指标聚类模式

生产规则常按类型分组指标:

字符串:
    // 类别A: 库指标
    $a1 = "SRWebSocket" ascii
    $a2 = "SocketRocket" ascii

    // 类别B: 行为指标
    $b1 = "SSH tunnel" ascii
    $b2 = "keylogger" ascii nocase

    // 类别C: C2模式
    $c1 = /https:\/\/[a-z0-9]{8,16}\.onion/

条件:
    filesize < 10MB and
    any of ($a*) and any of ($b*)  // 要求来自两类证据

为什么有效: 不同指标类型有不同置信度。单个C2域可能是决定性的,而您需要多个库导入才能有信心。通过 $a*, $b*, $c* 分组让您表达分级要求。