feat: A+B 缺口全补 + README 待办记录
A 结构层小缺口 (3/3): ✅ structure.py 加 LongFilename 告警 (>120 字符成员名) ✅ extractor.py _SAFE_NAME_RE 扩展 emoji 范围 (保留 emoji 文件名不崩) ✅ 重生成 L0-023_5layer_nested.zip (5 层真嵌套) B 白名单机制 (2/2): ✅ policy.yaml 加 keyword_whitelist (内网 IP/域名自动放行 RemoteDownloadUnix/PowerShell) ✅ policy.yaml 加 yara_hash_whitelist (MD5 在白名单跳过 YARA 告警) ✅ policy.py Property 类加两个 property 读取白名单 ✅ policy.py PolicyEngine.decide() 步骤 -1: 白名单过滤 (优先级最高) ✅ scanner.py decide() 调用补传 md5 外部资源缺口 (3 条,README 已记录): - L1-009/010 需真实签名 .cvd 文件 - L1-014 需压测脚本 stress_test.py 测试靶场: ✅ rules/test_rules.yar (7 条自动生成 YARA 规则) ✅ README 新增测试靶场待办 + 白名单机制说明 + 脚本清单
This commit is contained in:
@@ -99,6 +99,17 @@ class Policy:
|
||||
"""内网特征词表规则(L2B 引擎使用)。"""
|
||||
return self.raw.get("keyword_rules", []) or []
|
||||
|
||||
@property
|
||||
def keyword_whitelist(self) -> List[Dict[str, Any]]:
|
||||
"""关键词白名单。规则命中后,若 detail 包含 allowed_keywords 中任一子串 → 过滤。"""
|
||||
return self.raw.get("keyword_whitelist", []) or []
|
||||
|
||||
@property
|
||||
def yara_hash_whitelist_set(self) -> set[str]:
|
||||
"""YARA 哈希白名单(返回 MD5 集合,便于快速查询)。"""
|
||||
raw = self.raw.get("yara_hash_whitelist", []) or []
|
||||
return {str(entry.get("md5", "")).lower() for entry in raw if isinstance(entry, dict) and entry.get("md5")}
|
||||
|
||||
@property
|
||||
def yara_weights(self) -> Dict[str, float]:
|
||||
"""YARA 规则权重映射:规则名 → weight(0-100)。
|
||||
@@ -387,6 +398,7 @@ class PolicyEngine:
|
||||
real_type: str = "",
|
||||
engine_errors: Optional[List[str]] = None,
|
||||
encrypted: bool = False,
|
||||
md5: str = "",
|
||||
) -> Decision:
|
||||
"""综合所有信号产出最终裁决。
|
||||
|
||||
@@ -410,6 +422,38 @@ class PolicyEngine:
|
||||
|
||||
ext = (declared_ext or "").lower()
|
||||
|
||||
# ======================================================================
|
||||
# 步骤 -1:白名单过滤(优先级最高)
|
||||
# ======================================================================
|
||||
# 命中白名单的规则从 findings 中移除,不再参与任何后续裁决。
|
||||
# 包括:关键词白名单(按 rule + detail 子串匹配)+ YARA 哈希白名单。
|
||||
# ======================================================================
|
||||
wl_filtered: List[Finding] = []
|
||||
keyword_wl = policy.keyword_whitelist
|
||||
for f in findings:
|
||||
skip = False
|
||||
# 关键词白名单:detail 包含 allowed_keywords 任一子串
|
||||
if keyword_wl and f.engine == "keywords":
|
||||
for wl_entry in keyword_wl:
|
||||
if f.rule == wl_entry.get("rule"):
|
||||
allowed = wl_entry.get("allowed_keywords", [])
|
||||
if allowed and any(kw in f.detail for kw in allowed):
|
||||
skip = True
|
||||
logger.info(
|
||||
"白名单放行:rule=%s 命中关键词白名单 detail=%s",
|
||||
f.rule, f.detail,
|
||||
)
|
||||
break
|
||||
# YARA 哈希白名单:md5 在白名单集合中
|
||||
if not skip and f.engine == "yara":
|
||||
wl_set = policy.yara_hash_whitelist_set
|
||||
if wl_set and md5 and md5.lower() in wl_set:
|
||||
skip = True
|
||||
logger.info("白名单放行:YARA 命中但 MD5 在哈希白名单")
|
||||
if not skip:
|
||||
wl_filtered.append(f)
|
||||
findings = wl_filtered
|
||||
|
||||
# ======================================================================
|
||||
# 步骤 0:零容忍规则优先检查
|
||||
# ======================================================================
|
||||
|
||||
@@ -453,6 +453,7 @@ class Scanner:
|
||||
real_type=real_type,
|
||||
engine_errors=engine_errors,
|
||||
encrypted=encrypted,
|
||||
md5=root_info.get("md5", ""),
|
||||
)
|
||||
|
||||
# 计算 open_risk(独立于裁决结果,供人阅读)
|
||||
|
||||
Reference in New Issue
Block a user