yara-rule-authoring

yara-rule-authoring

热门

指导编写用于恶意软件识别的高质量 YARA-X 检测规则。适用于编写、审查或优化 YARA 规则等场景。涵盖命名规范、字符串提取与筛选、性能优化、传统 YARA 规则迁移以及降低误报率。触发词:YARA、YARA-X、恶意软件检测、威胁猎捕、IOC、特征码、crx 模块、dex 模块。

6336Star
545Fork
更新于 2026/7/30
SKILL.md
只读
名称
yara-rule-authoring
描述

指导编写用于恶意软件识别的高质量 YARA-X 检测规则。适用于编写、审查或优化 YARA 规则等场景。涵盖命名规范、字符串提取与筛选、性能优化、传统 YARA 规则迁移以及降低误报率。触发词:YARA、YARA-X、恶意软件检测、威胁猎捕、IOC、特征码、crx 模块、dex 模块。

YARA-X Rule Authoring

写出既能精准缉捕恶意软件、又不会让你淹没在误报海洋里的检测规则。

本 Skill 针对 YARA-X——基于 Rust 编写的新一代 YARA。YARA-X 为 VirusTotal 生产系统提供动力,也是官方推荐的实现版本。如果你手中已有旧版规则,请参考 从旧版 YARA 迁移

核心原则

  1. 字符串必须能生成优质 Atom(原子) — YARA 会提取 4 字节子串用于快速匹配。如果字符串包含重复字节、通用序列,或者长度不足 4 字节,会导致大量文件陷入低效的字节码验证流程。

  2. 锁定具体家族,而非泛泛的类别 — “检测勒索软件” 相当于啥都没检出;“检测 LockBit 3.0 配置提取 Routine” 才能精准命中目标。

  3. 上线部署前务必在白样本(Goodware)上测试 — 一条在 Windows 系统文件上乱报的规则毫无价值。上线前请在 VirusTotal 的白样本库或你自有的干净文件集中进行验证。

  4. 优先使用低开销检查进行 Short-circuit(短路逻辑) — 把 filesize < 10MB and uint16(0) == 0x5A4D 放在昂贵的字符串搜索或模块调用之前。

  5. Metadata 就是文档 — 未来的你(以及你的团队)需要清楚知道这条规则抓的是什么、为什么要抓、以及样本来自何处。

适用场景

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

禁用场景

  • 需要反汇编的静态分析 → 请使用 Ghidra/IDA 相关的 Skill
  • 动态恶意软件分析 → 请使用沙盒分析(Sandbox analysis)相关的 Skill
  • 基于网络的检测 → 请使用 Suricata/Snort 相关的 Skill
  • 使用 Volatility 进行内存取证 → 请使用内存取证相关的 Skill
  • 简单的 Hash 匹配检测 → 直接使用 Hash 清单即可

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 支持处理任何文件类型。请根据目标平台灵活调整匹配模式:

平台 Magic Bytes(魔数) 不推荐的字符串 推荐的字符串
Windows PE uint16(0) == 0x5A4D API 名称、Windows 常用路径 Mutex(互斥量)名称、PDB 路径
macOS Mach-O uint32(0) == 0xFEEDFACE (32位), 0xFEEDFACF (64位), 0xCAFEBABE (通用/Fat) 通用 Obj-C 方法名 键盘记录器特征串、持久化路径
JavaScript/Node (无需指定) require, fetch, axios 混淆器签名、eval+decode 链
npm/pip 包 (无需指定) postinstall, dependencies 可疑包名、数据外泄(Exfil)URL
Office 文档 uint32(0) == 0x504B0304 VBA 关键字 宏自动执行逻辑、编码后的 Payload
VS Code 插件 (无需指定) vscode.workspace 罕见的 activationEvents、隐藏文件访问逻辑
Chrome 扩展 使用 crx 模块 常用 Chrome API 权限滥用特征、manifest 异常配置
Android 应用 使用 dex 模块 标准 DEX 结构 被混淆的类名、可疑权限申请

macOS 恶意软件检测

目前尚无专属的 Mach-O 模块。可通过魔数校验 + 字符串特征组合实现检测:

魔数(Magic bytes):

// Mach-O 32-bit
uint32(0) == 0xFEEDFACE
// Mach-O 64-bit
uint32(0) == 0xFEEDFACF
// Universal binary (fat binary)
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 的示例模式:

rule SUSP_Mac_ProtonRAT
{
    strings:
        // 动态库特征
        $lib1 = "SRWebSocket" ascii
        $lib2 = "SocketRocket" ascii

        // 行为特征
        $behav1 = "SSH tunnel not launched" ascii
        $behav2 = "Keylogger" ascii

    condition:
        (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 模块
│  └─ 其他:锁定 manifest 配置文件模式、后台脚本(background script)行为
├─ 独立 JS 文件?
│  ├─ 排查混淆特征:eval+atob, fromCharCode 拼接链
│  ├─ 锁定独特的函数/变量名(即使压缩后往往也能留存)
│  └─ 检查加壳/编码后的 Payload
└─ 压缩/webpack 打包代码?
   ├─ 锁定打包后依然留存的独有字符串(URL、魔数/固定值)
   └─ 避开函数名(大部分会被混淆/破坏)

JavaScript 推荐的优质字符串:

  • 以太坊函数选择器(Function Selectors):{ 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 上线前在白样本库上进行持续集成测试

掌握这 5 个就够了,不要在繁复的工具列表中迷失方向。

应该摒弃的妥协念头(误区避坑)

当你产生以下想法时,请立刻打住并重新思考:

错误念头 专家解答
“这个通用的字符串应该足够独特了” 先拿白样本跑测试再说。你的直觉大概率是错的。
“yarGen 帮我提出了这些字符串” yarGen 只负责建议,你需要负责校验。请逐个人工核对。
“在我手头的 10 个样本上跑得挺好” 10 个样本 ≠ 生产环境。请使用 VirusTotal 的白样本库验证。
“写一条规则通杀所有变种” 这会导致误报刷屏。请精准锁定具体家族。
“万一真误报了,我再去把规则改精准点” 规则上线前就要写严谨。误报会极大地消耗团队信任度。
“这个十六进制模式绝对独特” 在单一样本里独特 ≠ 在整个恶意软件生态中独特。
“性能慢点无所谓” 只要有一条慢规则,就会拖慢整个规则集。请优化 Atom。
“PEiD 规则现在还能用” 早过时了。32 位加壳工具在现代威胁中已无实际参考价值。
“我以后再补充更多条件” 带着缺陷上线规则等于埋雷。
"这只是用来做 Threat Hunting(威胁猎捕)的" Hunting 规则最终都会变成检测规则,质量标准应完全一致。
“这个 API 名称证明它就是恶意软件” 合法软件也会使用相同的 API。需要结合上下文行为判断。
“对于这些通用字符串,用 any of 就挺好” 通用字符串 + any of = 误报灾难。any of 只能用于本身就足够独特的字符串。
“这个正则表达式足够精准了” /fetch.*token/ 会匹配到所有的鉴权代码。必须限定外泄目的地要求。
“这段 JavaScript 看着挺干净的” 攻击者会向合法代码中注入恶意代码。仔细检查是否存在 eval+decode 链。
“用 .* 匹配更灵活” 无界正则表达式 = 性能崩盘 + 内存爆炸。请使用 .{0,30} 限定范围。
“我在所有地方都加上 --relaxed-re-syntax” 这会掩盖真实的逻辑 Bug。请去修复正则本身,而不是掩耳盗盗。

决策树

这个字符串够好吗?

这个字符串够好吗?
├─ 长度小于 4 字节?
│  └─ 否 — 寻找更长的字符串
├─ 包含重复字节 (如 0000, 9090)?
│  └─ 否 — 补充上下文环境信息
├─ 是 API 名称 (如 VirtualAlloc, CreateRemoteThread)?
│  └─ 否 — 改用调用位置(Call site)的十六进制模式
├─ 出现在 Windows 系统文件中?
│  └─ 否 — 太过通用,去寻找独特的特征
├─ 是常用路径 (如 C:\Windows\, cmd.exe)?
│  └─ 否 — 去寻找该恶意软件独有的路径
├─ 该恶意软件家族独有?
│  └─ 是 — 直接使用
└─ 也出现在其他恶意软件中?
   └─ 也许 — 结合家族专属的标记组合使用

什么时候用 "all of" vs "any of"

应该要求匹配所有字符串 (all of) 还是允许任意匹配 (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 个以上命中 = 推翻重来。

  • 即使优化后性能依然极差 → 属于架构问题。拆分为多条聚焦的细分规则,或添加严格的前置预过滤条件。

  • 很难写出 Description 说明 → 说明规则逻辑太模糊。如果你连它抓的是什么都说不清,那它抓到的东西绝对太多了。

排查与调试误报

误报排查流程:
│
├─ 1. 到底是哪个字符串命中了?
│     运行:yr scan -s rule.yar false_positive.exe
│
├─ 2. 存在于合法的第三方库中吗?
│     └─ 解决:添加 not $fp_vendor_string 排除条件
│
├─ 3. 是常见的开发代码模式吗?
│     └─ 解决:寻找更具体的特征指标,替换掉该字符串
│
├─ 4. 是否多个通用字符串同时命中了?
│     └─ 解决:收紧条件要求全匹配 (all) + 添加独有的标志位
│
└─ 5. 恶意软件使用了通用技术手段吗?
      └─ 解决:锁定恶意软件具体的实现细节,而不是技术手段本身

十六进制 (Hex) vs 文本 (Text) vs 正则 (Regex)

我应该使用哪种字符串类型?
│
├─ 精确的 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)

样本加壳了吗?(优先检查)

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

样本加壳了吗?
├─ 熵 (Entropy) > 7.0?
│  └─ 很可能加壳了 — 先提取未加壳的 Payload 层
├─ 几乎没有可读字符串?
│  └─ 很可能加壳了 — 利用熵、PE 结构或壳特征码
├─ 检出了 UPX/MPRESS/自定义壳?
│  └─ 针对解壳后的 Payload 编写规则,或者直接检测壳本身
└─ 存在丰富的可读字符串?
   └─ 继续使用基于字符串的检测方案

专家建议: 不要针对壳代码层写检测规则。壳经常变,但里面的 Payload 不会变。

当字符串失效时,转向结构分析

如果 yarGen 提取出来的全是 API 名称和通用路径:

St

<!-- truncated for translation batch; full body continues in source -->