fix: 六引擎误报根因修复 — 解包递归、YARA 恒真规则、签名分级、real_type 溢出

检测范围与证据链修复,不改裁决口径(口径改动在下一条提交)。

- extractor:zip/tar 成员在超限分支外漏加回扫描队列,解包后内容永远不参与检测;
  zip 目录条目被当成内嵌对象;tar 超限成员先落盘不删。递归真正生效后深扫耗时可测。
- clamav:_HIGH/_MEDIUM/_UNWANTED 关键词是小写,而签名名是 "Win.Trojan..." 大小写混排,
  分级判定恒不命中全走默认档;改统一大写匹配。超过 clamd MaxFileSize 的裸奔区间
  (1G~1.5G) 新增 ClamAVSkippedSizeLimit(30) — 按"不可扫描不放行"进复核。
- yara:pe.yar C1 系列改用导入表判定,不再靠裸子串命中字符串表;
  linux.yar C7 多条规则条件恒真(裸 nc/fetch 之类)已收紧;C8/C3 相应收窄。
- structure:DangerousExecutableExtension 是载体信号而非恶意行为,critical 权重 45→35,
  不再作为把中低置信度信号一起顶过 block_score 的底座。
- scanner/documents:real_type 拼进 libmagic 对 MSI/OLE 的元数据串实测 334+ 字符,
  超列宽导致整条 scan_tasks INSERT 连 findings 一起丢(被拒文件不留痕)→
  列宽 256→512,migrate.sql 补 ALTER。
This commit is contained in:
2026-11-02 20:26:56 +08:00
parent 64b682319e
commit b6a004bdb7
13 changed files with 636 additions and 311 deletions

View File

@@ -126,26 +126,41 @@ rule C8_Ransomware_Note_Filename {
meta:
risk_level = "medium"
category = "C8"
false_positive_rate = "medium"
false_positive_rate = "low"
reference = "勒索信文件名通用模式"
description = "勒索信典型文件名变体(匹配后触发需要配合加密 API 才升级高危)"
description = "勒索信文件名 + (加密 API + 赎金语言)或(赎金语言 + 钱包地址)"
strings:
// 只保留"文件名形态"的勒索信特征:家族专有名 + 扩展名。
// 不再用裸 README.txt / _readme.txt:任何安装包都带这两个字面量,
// 在二进制内容上做全文匹配时必然命中(Go 官方 MSI 即被这样判成恶意)。
$n1 = /HOW_TO_RECOVER[\w.-]*\.(txt|html|png|bmp|jpg|url|vbs|js)/ nocase
$n2 = /RESTORE_FILES[\w.-]*\.(txt|html|png|bmp|jpg|url|vbs|js)/ nocase
$n3 = /DECRYPT_INSTRUCTIONS[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n4 = /README[_\s-]*[\d]*[_\s-]*[\w]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n4 = /README[._-]*(FOR[._-]*DECRYPT|TO[._-]*RESTORE)[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n5 = /HELP_DECRYPT[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n6 = /_readme[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n7 = /_restore[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$bitcoin = /bitcoin address|BTC\b|monero address|XMR\b|send money|ransom|payment/ nocase
$wallet = /1[A-Za-z0-9]{25,34}|bc1[A-Za-z0-9]{11,71}|4[0-9A-Za-z]{32}/ nocase
$n6 = /\b_(readme|restore)[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
$n7 = /(how_to_decrypt|restore_my_files|decrypt_your_files)[\w.-]*\.(txt|html)/ nocase
// 赎金语言:必须是完整词组。裸 "BTC"/"XMR"/"payment"/"ransom" 在压缩流里
// 会以随机字节出现,"ransom" 还会被 "Ransomware" 子串命中。
$payment = /(bitcoin|monero|xmr|btc)\s+(address|wallet)|send\s+(the\s+)?money|pay\s+(the\s+)?(ransom|fee)|\bransom\b\s+(note|payment|demand)|your\s+files\s+(are\s+)?encrypted|decrypt\s+your\s+files/ nocase
// 钱包地址:锚定到整个 token,并用真实地址字符集/长度。
// 原写法 1[A-Za-z0-9]{25,34} 无边界,单个 56MB 安装包命中 7.6 万次。
$btc_addr = /\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/
$bech32 = /\bbc1q[a-z0-9]{38}\b|\bbc1q[a-z0-9]{58}\b/
$xmr_addr = /\b[48][0-9A-Za-z]{94}\b/
$encapi = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
condition:
// 勒索信文件名 + 加密 API = 明确勒索
any of ($n*) and $encapi
or
// 勒索信文件名 + 比特币/XMR 地址 = 大概率勒索
any of ($n*) and any of ($bitcoin, $wallet)
any of ($n*)
and (
// 投递器:真加密 API + 赎金语言
($encapi and $payment)
or
// 纯文本勒索信:赎金语言 + 具体钱包地址
($payment and any of ($btc_addr, $bech32, $xmr_addr))
)
}
@@ -199,11 +214,13 @@ rule C8_Ransomware_VolumeShadow {
$vss2 = /vssadmin\s+delete\s+shadows\s+\/all\b/ ascii
$wmic1 = /wmic\s+shadowcopy\s+delete/ ascii
$wmic2 = /wmic\s+shadowcopy\s+where\s+\d+/ ascii
$vss3 = /ShadowCopy|VolumeShadowCopy|vss\b/i ascii // "i" flag = nocase in YARA
$vss4 = /vssadmin[^\n]{0,48}delete[^\n]{0,48}(shadows|shadow\s+copies)/ ascii
$enc = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
condition:
// 卷影删除 + 加密 API = 完整勒索前置
(any of ($vss1, $vss2, $wmic*, $vss3)) and any of ($enc*)
// 不用裸 "vss"/"ShadowCopy" 子串:任何备份/卷影库的符号表都有它们,
// 和 CryptEncrypt 同框就报勒索,是典型误报来源。
(any of ($vss1, $vss2, $wmic*, $vss4)) and any of ($enc*)
or
// 连续多次 vssadmin delete = 正在清卷影
any of ($vss1, $vss2) and any of ($wmic*)