MemScan-EDR/src-csharp/MemScanEDR/Services/RuleEngine.cs

404 lines
16 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using MemScanEDR.Models;
namespace MemScanEDR.Services;
/// <summary>
/// MITRE ATT&CK 规则引擎 —— 第三层复核
/// 基于 MITRE ATT&CK 框架中的内存攻击技术,对 AI 判定结果进行交叉验证
/// 降低误报AI 标记但规则不匹配 → 降级
/// 提高准确率AI + 规则双重确认 → 确认为恶意
/// </summary>
public class RuleEngine
{
private readonly List<MitreRule> _rules;
public RuleEngine()
{
_rules = BuildMitreRules();
}
/// <summary>
/// 对 AI 分类结果进行规则复核
/// </summary>
public RuleValidationResult Validate(MemoryFeatures features, ClassificationResult aiResult,
BaselineResult baselineResult)
{
var result = new RuleValidationResult();
var matchedRules = new List<MitreRule>();
var totalScore = 0.0;
foreach (var rule in _rules)
{
var (matched, confidence) = rule.Evaluate(features);
if (matched)
{
matchedRules.Add(rule);
totalScore += confidence;
result.MatchedTechniques.Add(rule.TechniqueId);
}
}
result.MatchedRuleCount = matchedRules.Count;
result.RuleConfidenceScore = Math.Min(totalScore / Math.Max(_rules.Count, 1), 1.0);
// ─── 三级交叉验证 ───
// AI 分数 + 基线异常 + 规则匹配 = 综合判定
result.AiScore = aiResult.FinalScore;
result.BaselineAnomalyScore = baselineResult.AnomalyScore;
result.RuleScore = result.RuleConfidenceScore;
// 综合分AI 40% + 基线 30% + 规则 30%
var combinedScore = aiResult.FinalScore * 0.40 +
baselineResult.AnomalyScore * 0.30 +
result.RuleConfidenceScore * 0.30;
result.CombinedScore = Math.Min(combinedScore, 1.0);
// 最终风险等级
result.FinalRiskLevel = result.CombinedScore switch
{
>= 0.75 => RiskLevel.High,
>= 0.45 => RiskLevel.Suspicious,
_ => RiskLevel.Safe
};
// ─── 误报修正逻辑 ───
ApplyFalsePositiveCorrections(result, features);
// 生成综合解释
result.Reasoning = BuildReasoning(result, features, matchedRules);
return result;
}
/// <summary>
/// 误报修正 —— 对AI高分但规则不匹配的情况进行降级
/// </summary>
private static void ApplyFalsePositiveCorrections(RuleValidationResult result, MemoryFeatures features)
{
// 修正1: JIT 编译器合法 RWX (.NET, Java, V8)
if (features.RwxPrivatePages > 0 && result.MatchedRuleCount == 0)
{
var name = features.ProcessName.ToLowerInvariant();
var isRuntime = name.Contains("dotnet") || name.Contains("java") ||
name.Contains("node") || name.Contains("python") ||
name.Contains("chrome") || name.Contains("msedge") ||
name.Contains("firefox");
if (isRuntime && features.IsSystemPath && features.IsSigned)
{
// JIT 运行时正常使用 RWX降级
result.FinalRiskLevel = RiskLevel.Safe;
result.CombinedScore = Math.Min(result.CombinedScore, 0.25);
result.FalsePositiveCorrection = "JIT运行时合法RWX内存.NET/Java/V8引擎";
}
}
// 修正2: 安全软件正常行为
if (features.SuspiciousApiStrings.Count > 0 && result.MatchedRuleCount <= 1)
{
var nameLower = features.ProcessName.ToLowerInvariant();
var isSecurity = nameLower.Contains("defender") || nameLower.Contains("antivirus") ||
nameLower.Contains("security") || nameLower.Contains("edr") ||
nameLower.Contains("sentinel") || nameLower.Contains("crowd") ||
nameLower.Contains("carbon") || nameLower.Contains("mcafee");
if (isSecurity && features.IsSigned)
{
result.FinalRiskLevel = RiskLevel.Safe;
result.CombinedScore = Math.Min(result.CombinedScore, 0.20);
result.FalsePositiveCorrection = "安全软件正常行为特征";
return; // 已经确定是误报,无需继续检查
}
}
// 修正2.5: 脚本引擎/Shell自身字符串误匹配
if (features.SuspiciousStringHits > 0 && result.MatchedRuleCount <= 1)
{
var nameLower = features.ProcessName.ToLowerInvariant();
var isScriptEngine = nameLower is "powershell.exe" or "pwsh.exe" or "powershell_ise.exe"
or "cmd.exe" or "wscript.exe" or "cscript.exe" or "conhost.exe"
or "python.exe" or "python3.exe" or "wsl.exe" or "bash.exe";
if (isScriptEngine && features.IsSigned && features.IsSystemPath)
{
result.FinalRiskLevel = RiskLevel.Safe;
result.CombinedScore = Math.Min(result.CombinedScore, 0.15);
result.FalsePositiveCorrection = "脚本引擎自身合法字符串(非恶意注入)";
return;
}
}
// 修正3: 开发工具调试行为
if (features.SuspiciousApiStrings.Count > 0 && result.MatchedRuleCount <= 1)
{
var exeLower = features.ExePath.ToLowerInvariant();
var isDev = exeLower.Contains("visual studio") || exeLower.Contains("jetbrains") ||
exeLower.Contains("vscode") || exeLower.Contains("debugger") ||
exeLower.Contains("ollydbg") || exeLower.Contains("x64dbg") ||
exeLower.Contains("windbg") || exeLower.Contains("ida");
if (isDev)
{
result.FinalRiskLevel = RiskLevel.Safe;
result.CombinedScore = Math.Min(result.CombinedScore, 0.30);
result.FalsePositiveCorrection = "开发/调试工具正常行为";
}
}
}
private static string BuildReasoning(RuleValidationResult result, MemoryFeatures f,
List<MitreRule> matchedRules)
{
var parts = new List<string>();
if (result.FalsePositiveCorrection != null)
{
parts.Add($"误报修正: {result.FalsePositiveCorrection}");
}
if (matchedRules.Count > 0)
{
var ruleDescriptions = matchedRules.Take(3)
.Select(r => $"{r.TechniqueId} ({r.TechniqueName})");
parts.Add($"匹配MITRE规则: {string.Join(", ", ruleDescriptions)}");
}
if (f.RwxPrivatePages > 0)
parts.Add($"RWX私有页: {f.RwxPrivatePages}");
if (f.PeMismatchDisk)
parts.Add("Process Hollowing 特征");
if (f.SuspiciousStringHits > 0)
parts.Add($"敏感字符串命中: {f.SuspiciousStringHits}");
parts.Add($"综合评分: AI={result.AiScore:F2} 基线={result.BaselineAnomalyScore:F2} 规则={result.RuleScore:F2} → {result.CombinedScore:F2}");
return string.Join(" | ", parts);
}
// ─── MITRE ATT&CK 内存攻击规则库 ───
private static List<MitreRule> BuildMitreRules() => new()
{
// T1055: Process Injection
new MitreRule
{
TechniqueId = "T1055",
TechniqueName = "进程注入",
Description = "通过 VirtualAllocEx/WriteProcessMemory/CreateRemoteThread 实现跨进程代码注入",
EvaluateFunc = f => f.RwxPrivatePages > 0 &&
f.SuspiciousApiStrings.Any(a =>
a.Contains("VirtualAllocEx", StringComparison.OrdinalIgnoreCase) ||
a.Contains("WriteProcessMemory", StringComparison.OrdinalIgnoreCase) ||
a.Contains("CreateRemoteThread", StringComparison.OrdinalIgnoreCase))
},
// T1055.012: Process Hollowing
new MitreRule
{
TechniqueId = "T1055.012",
TechniqueName = "进程掏空 (Process Hollowing)",
Description = "创建挂起进程后掏空原始代码,替换为恶意载荷",
EvaluateFunc = f => f.PeMismatchDisk
},
// T1055.001: Dynamic-link Library Injection
new MitreRule
{
TechniqueId = "T1055.001",
TechniqueName = "DLL注入",
Description = "通过 LoadLibrary/CreateRemoteThread 注入恶意DLL",
EvaluateFunc = f => f.SuspiciousApiStrings.Any(a =>
a.Contains("LoadLibrary", StringComparison.OrdinalIgnoreCase) ||
a.Contains("LdrLoadDll", StringComparison.OrdinalIgnoreCase)) &&
f.SuspiciousApiStrings.Any(a =>
a.Contains("CreateRemoteThread", StringComparison.OrdinalIgnoreCase))
},
// T1620: Reflective Code Loading
new MitreRule
{
TechniqueId = "T1620",
TechniqueName = "反射代码加载",
Description = "在内存中直接加载PE/DLL不通过标准 LoadLibrary",
EvaluateFunc = f => f.AnonymousExecPages > 0 &&
f.RwxPrivatePages > 0 &&
f.SuspiciousStrings.Any(s =>
s.Contains("ReflectiveLoader", StringComparison.OrdinalIgnoreCase))
},
// T1574.002: DLL Side-Loading
new MitreRule
{
TechniqueId = "T1574.002",
TechniqueName = "DLL侧加载",
Description = "利用合法程序的DLL搜索顺序加载恶意DLL",
EvaluateFunc = f => f.TempPathModules > 0 && f.IsSigned && f.IsSystemPath
},
// T1071: Application Layer Protocol (C2)
new MitreRule
{
TechniqueId = "T1071",
TechniqueName = "C2 通信",
Description = "通过应用层协议与C2服务器通信",
EvaluateFunc = f => f.ForeignConnections > 0 &&
f.SuspiciousPortConnections > 0 &&
f.SuspiciousApiStrings.Any(a =>
a.Contains("connect", StringComparison.OrdinalIgnoreCase) ||
a.Contains("InternetConnect", StringComparison.OrdinalIgnoreCase))
},
// T1095: Non-Application Layer Protocol
new MitreRule
{
TechniqueId = "T1095",
TechniqueName = "非标准协议通信",
Description = "使用非标准协议的网络通信",
EvaluateFunc = f => f.NonStandardPortConnections >= 2 &&
f.ForeignConnections > 0
},
// T1027: Obfuscated Files or Information
new MitreRule
{
TechniqueId = "T1027",
TechniqueName = "代码混淆/加密",
Description = "内存中存在加密或混淆载荷",
EvaluateFunc = f => f.MaxEntropy > 7.2 &&
f.HighEntropyRegions >= 2 &&
f.AnonymousExecPages > 0
},
// T1003.001: LSASS Memory (Credential Dumping)
new MitreRule
{
TechniqueId = "T1003.001",
TechniqueName = "LSASS 凭据转储",
Description = "访问 LSASS 进程内存提取凭据",
EvaluateFunc = f => f.ProcessName.Equals("lsass.exe", StringComparison.OrdinalIgnoreCase) &&
f.SuspiciousApiStrings.Any(a =>
a.Contains("MiniDump", StringComparison.OrdinalIgnoreCase) ||
a.Contains("SamOpenUser", StringComparison.OrdinalIgnoreCase)) ||
f.SuspiciousStrings.Any(s =>
s.Contains("lsass", StringComparison.OrdinalIgnoreCase))
},
// T1036.005: Match Legitimate Name or Location
new MitreRule
{
TechniqueId = "T1036.005",
TechniqueName = "进程名伪装",
Description = "使用合法的系统进程名但位于非系统路径",
EvaluateFunc = f => f.IsSystemProcessName && !f.IsSystemPath
},
// T1547.001: Registry Run Keys
new MitreRule
{
TechniqueId = "T1547.001",
TechniqueName = "注册表持久化",
Description = "通过注册表run键实现持久化驻留",
EvaluateFunc = f => f.SuspiciousStrings.Any(s =>
s.Contains("Run", StringComparison.OrdinalIgnoreCase) &&
(s.Contains("SOFTWARE\\Microsoft\\Windows\\CurrentVersion", StringComparison.OrdinalIgnoreCase) ||
s.Contains("RunOnce", StringComparison.OrdinalIgnoreCase)))
},
// T1496: Resource Hijacking (Crypto Mining)
new MitreRule
{
TechniqueId = "T1496",
TechniqueName = "资源劫持 (挖矿)",
Description = "劫持系统资源进行加密货币挖矿",
EvaluateFunc = f => f.SuspiciousStrings.Any(s =>
s.Contains("stratum", StringComparison.OrdinalIgnoreCase) ||
s.Contains("cryptonight", StringComparison.OrdinalIgnoreCase) ||
s.Contains("coinmine", StringComparison.OrdinalIgnoreCase) ||
s.Contains("mining", StringComparison.OrdinalIgnoreCase))
},
// T1486: Data Encrypted for Impact (Ransomware)
new MitreRule
{
TechniqueId = "T1486",
TechniqueName = "勒索加密",
Description = "加密文件以勒索赎金",
EvaluateFunc = f => f.SuspiciousStrings.Any(s =>
s.Contains("ENCRYPTED", StringComparison.OrdinalIgnoreCase) ||
s.Contains("ransom", StringComparison.OrdinalIgnoreCase) ||
s.Contains("decrypt", StringComparison.OrdinalIgnoreCase)) &&
f.MaxEntropy > 7.0
},
// T1562.001: Disable or Modify Tools
new MitreRule
{
TechniqueId = "T1562.001",
TechniqueName = "禁用安全工具",
Description = "禁用或修改安全软件",
EvaluateFunc = f => f.SuspiciousApiStrings.Any(a =>
a.Contains("AdjustTokenPrivileges", StringComparison.OrdinalIgnoreCase)) &&
f.IsSystemProcessName
},
// T1106: Native API
new MitreRule
{
TechniqueId = "T1106",
TechniqueName = "Native API 调用",
Description = "通过NT原生API绕过用户态Hook",
EvaluateFunc = f => f.SuspiciousApiStrings.Count(a =>
a.StartsWith("Nt", StringComparison.OrdinalIgnoreCase)) >= 2
},
};
}
/// <summary>
/// MITRE ATT&CK 单条规则定义
/// </summary>
public class MitreRule
{
public string TechniqueId { get; init; } = "";
public string TechniqueName { get; init; } = "";
public string Description { get; init; } = "";
public Func<MemoryFeatures, bool> EvaluateFunc { get; init; } = _ => false;
/// <summary>
/// 评估规则,返回 (是否匹配, 置信度)
/// </summary>
public (bool matched, double confidence) Evaluate(MemoryFeatures features)
{
try
{
var match = EvaluateFunc(features);
return (match, match ? 1.0 : 0.0);
}
catch
{
return (false, 0);
}
}
}
/// <summary>
/// 规则引擎验证结果
/// </summary>
public class RuleValidationResult
{
public double AiScore { get; set; }
public double BaselineAnomalyScore { get; set; }
public double RuleScore { get; set; }
public double CombinedScore { get; set; }
public RiskLevel FinalRiskLevel { get; set; } = RiskLevel.Safe;
public int MatchedRuleCount { get; set; }
public List<string> MatchedTechniques { get; set; } = new();
public double RuleConfidenceScore { get; set; }
public string Reasoning { get; set; } = "";
public string? FalsePositiveCorrection { get; set; }
}