名称: yara-规则编写 描述: > 指导编写高质量的YARA-X检测规则用于恶意软件识别。 当编写、审查或优化YARA规则时使用。涵盖命名约定、字符串选择、性能优化、从旧版YARA迁移、减少误报。触发词: YARA, YARA-X, 恶意软件检测, 威胁狩猎, IOC, 签名, crx模块, dex模块。
YARA-X规则编写
编写检测规则以捕获恶意软件而不陷入误报泛滥。
此技能针对YARA-X,基于Rust的旧版YARA的后继者。YARA-X驱动VirusTotal的生产系统,是推荐实现。如果您有现有规则,请参见从旧版YARA迁移。
核心原则
-
字符串必须生成良好的原子 — YARA提取4字节子序列以进行快速匹配。具有重复字节、常见序列或少于4字节的字符串会迫使在太多文件上执行缓慢的字节码验证。
-
针对特定家族,而非类别 — “检测勒索软件” 什么都抓不到。“检测LockBit 3.0配置提取例程” 捕获您想要的内容。
-
部署前测试对抗良性软件 — 在Windows系统文件上触发的规则是无用的。使用VirusTotal的良性软件语料库或您自己的清洁文件集进行验证。
-
首先使用廉价检查短路 — 将
filesize < 10MB and uint16(0) == 0x5A4D放在昂贵的字符串搜索或模块调用之前。 -
元数据是文档 — 未来的您(和您的团队)需要知道这捕获了什么、为什么以及样本来自何处。
何时使用
- 为恶意软件检测编写新的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% 变体的规则太窄;匹配良性软件的太宽。
修饰符纪律:
- 永不投机使用
nocase或wide— 仅当您有确认证据表明样本中大小写/编码变化时使用 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 静默文字 |
\\R 或 R |
| 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 获取完整决策树和示例。
条件模式
为短路排序条件:
filesize < 10MB(瞬时)uint16(0) == 0x5A4D(近乎瞬时)- 字符串匹配 (廉价)
- 模块检查 (昂贵)
参见 performance.md 获取详细优化模式。
工作流
- 收集样本 — 多个样本;单样本规则脆弱
- 提取候选 —
yarGen -m samples/ --excludegood - 验证质量 — 使用决策树;yarGen需要80%过滤
- 编写初始规则 — 遵循模板和适当元数据
- 整理和测试 —
yr check,yr fmt, 整理脚本 - 良性软件验证 — VirusTotal语料库或本地清洁文件
- 部署 — 添加仓库并带完整元数据,监控误报
参见 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* 分组让您表达分级要求。