280 lines
10 KiB
C#
280 lines
10 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using MemScanEDR.Models;
|
||
|
||
namespace MemScanEDR.Services;
|
||
|
||
/// <summary>
|
||
/// 三级联动检测管线 —— 2.0 核心编排引擎
|
||
///
|
||
/// 流程:
|
||
/// [快速预过滤] → [第一层: 基线异常检测] → [第二层: 监督分类] → [第三层: MITRE规则复核] → 输出
|
||
///
|
||
/// 速度优化:
|
||
/// - 预过滤阶段不读内存,仅元数据判断,跳过 >80% 的进程
|
||
/// - 只在可疑进程上执行完整特征提取
|
||
/// - 基线匹配失败时提前退出,节省计算
|
||
/// </summary>
|
||
public class DetectionPipeline
|
||
{
|
||
private readonly BaselineEngine _baselineEngine;
|
||
private readonly ClassificationEngine _classificationEngine;
|
||
private readonly RuleEngine _ruleEngine;
|
||
private readonly FeatureExtractor _featureExtractor;
|
||
private readonly MemoryScanner _memoryScanner;
|
||
private readonly BaselineLibrary _baselineLibrary;
|
||
|
||
// 扫描模式
|
||
private readonly ScanMode _mode;
|
||
|
||
public DetectionPipeline(ScanMode mode = ScanMode.Balanced)
|
||
{
|
||
_mode = mode;
|
||
_baselineLibrary = BaselineLibrary.CreateDefault();
|
||
_baselineEngine = new BaselineEngine(_baselineLibrary);
|
||
_classificationEngine = new ClassificationEngine();
|
||
_ruleEngine = new RuleEngine();
|
||
_featureExtractor = new FeatureExtractor();
|
||
_memoryScanner = new MemoryScanner();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 完整三级检测流程
|
||
/// </summary>
|
||
public Task<ScanResult> AnalyzeAsync(ProcessInfo proc, List<Signature> signatures)
|
||
{
|
||
return Task.FromResult(Analyze(proc, signatures));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 完整三级检测流程(同步核心)
|
||
/// </summary>
|
||
private ScanResult Analyze(ProcessInfo proc, List<Signature> signatures)
|
||
{
|
||
var sw = Stopwatch.StartNew();
|
||
|
||
// ─── 阶段0: 快速预过滤(不读内存)───
|
||
var memoryRegions = _memoryScanner.GetMemoryRegions(proc.Pid);
|
||
proc.MemoryRegions = memoryRegions;
|
||
var signatureMatches = new List<SignatureMatch>();
|
||
|
||
var preFilterResult = QuickPreFilter(proc, memoryRegions);
|
||
if (preFilterResult.canSkip)
|
||
{
|
||
return new ScanResult
|
||
{
|
||
Pid = proc.Pid,
|
||
ProcessName = proc.Name,
|
||
RiskLevel = RiskLevel.Safe,
|
||
RiskScore = preFilterResult.score,
|
||
Indicators = new List<string>(),
|
||
Reasoning = preFilterResult.reason,
|
||
AIProvider = "pipeline-v2/fast-filter",
|
||
DetectionLayer = "PreFilter",
|
||
ScanTime = DateTime.Now
|
||
};
|
||
}
|
||
|
||
// ─── 阶段1: 内存区域扫描(轻量)───
|
||
if (_mode != ScanMode.Fast)
|
||
{
|
||
var suspiciousRegions = _memoryScanner.GetSuspiciousRegions(proc.Pid);
|
||
if (suspiciousRegions.Count > 0 || proc.IsTempPath || !proc.IsSigned)
|
||
{
|
||
signatureMatches = _memoryScanner.ScanProcess(proc.Pid, signatures);
|
||
}
|
||
}
|
||
|
||
// ─── 阶段2: 特征提取 ───
|
||
MemoryFeatures features;
|
||
if (_mode == ScanMode.Fast)
|
||
{
|
||
features = _featureExtractor.QuickExtract(proc, memoryRegions);
|
||
}
|
||
else
|
||
{
|
||
features = _featureExtractor.Extract(proc, memoryRegions, signatureMatches, signatures);
|
||
}
|
||
|
||
// ─── 第一层: 无监督基线检测 ───
|
||
var baselineResult = _baselineEngine.Analyze(features);
|
||
|
||
// 完全匹配基线 → 直接判定为正常
|
||
if (baselineResult.Classification == BaselineClassification.Normal &&
|
||
baselineResult.AnomalyScore < 0.20)
|
||
{
|
||
return BuildSafeResult(proc, features, baselineResult, signatureMatches,
|
||
$"第一层 | 进程内存结构完全匹配正常基线 [{baselineResult.BaselineName}] | 异常分数={baselineResult.AnomalyScore:F3}");
|
||
}
|
||
|
||
// ─── 第二层: 监督分类 ───
|
||
var classificationResult = _classificationEngine.Classify(features);
|
||
|
||
// 分类为良性 + 基线无异常 → 安全
|
||
if (classificationResult.Classification == MalwareClass.Benign &&
|
||
baselineResult.AnomalyScore < 0.40)
|
||
{
|
||
return BuildSafeResult(proc, features, baselineResult, signatureMatches,
|
||
$"第二层 | 分类器判定良性 | {classificationResult.SuspectedFamily}");
|
||
}
|
||
|
||
// ─── 第三层: MITRE ATT&CK规则复核 ───
|
||
var ruleResult = _ruleEngine.Validate(features, classificationResult, baselineResult);
|
||
|
||
// ─── 构建最终结果 ───
|
||
var indicators = BuildIndicators(features, baselineResult, classificationResult, ruleResult);
|
||
var layer = DetermineDetectionLayer(baselineResult, classificationResult, ruleResult);
|
||
|
||
return new ScanResult
|
||
{
|
||
Pid = proc.Pid,
|
||
ProcessName = proc.Name,
|
||
RiskLevel = ruleResult.FinalRiskLevel,
|
||
RiskScore = ruleResult.CombinedScore,
|
||
Indicators = indicators,
|
||
Reasoning = ruleResult.Reasoning,
|
||
Matches = signatureMatches,
|
||
AIProvider = $"pipeline-v2/{_mode.ToString().ToLower()}",
|
||
DetectionLayer = layer,
|
||
ScanTime = DateTime.Now
|
||
};
|
||
}
|
||
|
||
// ─── 快速预过滤 ───
|
||
private static (bool canSkip, double score, string reason) QuickPreFilter(
|
||
ProcessInfo proc, List<MemoryRegion> regions)
|
||
{
|
||
double score = 0;
|
||
var reasons = new List<string>();
|
||
|
||
// 已签名 + 系统路径 + 无网络 → 几乎肯定安全
|
||
if (proc.IsSigned && proc.IsSystemPath && proc.Connections.Count == 0)
|
||
{
|
||
// 再检查是否有可疑内存区域
|
||
var hasRwx = regions.Any(r =>
|
||
r.Protect.Contains("EXECUTE_READWRITE") && r.Type == "PRIVATE");
|
||
|
||
if (!hasRwx && !proc.IsTempPath)
|
||
{
|
||
return (true, 0, $"预过滤 | 已签名系统程序 | PID={proc.Pid} {proc.Name}");
|
||
}
|
||
|
||
// 脚本引擎/Shell 有合法RWX(JIT),即使有RWX也是正常的
|
||
if (hasRwx && FeatureExtractor.IsScriptingEngine(proc))
|
||
{
|
||
return (true, 0.05, $"预过滤 | 已签名脚本引擎(RWX为JIT正常行为) | PID={proc.Pid} {proc.Name}");
|
||
}
|
||
}
|
||
|
||
// 未签名 + 临时路径 → 需要进一步分析
|
||
if (!proc.IsSigned && proc.IsTempPath)
|
||
score += 0.30;
|
||
|
||
// 系统进程名 + 非系统路径 → 可疑
|
||
if (FeatureExtractor.IsSystemProcessName(proc.Name) && !proc.IsSystemPath)
|
||
score += 0.35;
|
||
|
||
// 网络连接到可疑端口
|
||
if (proc.Connections.Any(c => IsSuspiciousPort(c.RemotePort)))
|
||
score += 0.25;
|
||
|
||
// RWX 私有页
|
||
if (regions.Any(r => r.Protect.Contains("EXECUTE_READWRITE") && r.Type == "PRIVATE"))
|
||
score += 0.20;
|
||
|
||
if (score < 0.05)
|
||
return (true, 0, $"预过滤 | 无可疑特征 | PID={proc.Pid} {proc.Name}");
|
||
|
||
if (score < 0.15 && proc.IsSigned)
|
||
return (true, score * 0.5, $"预过滤 | 已签名低风险 | PID={proc.Pid} {proc.Name} | score={score:F2}");
|
||
|
||
return (false, score, $"预过滤 | 进入AI分析 | PID={proc.Pid} {proc.Name} | score={score:F2}");
|
||
}
|
||
|
||
private static bool IsSuspiciousPort(int port) => port switch
|
||
{
|
||
4444 or 5555 or 6666 or 7777 or 1337 or 31337 or 9999 or 12345 or 27015 => true,
|
||
_ => false
|
||
};
|
||
|
||
private static ScanResult BuildSafeResult(ProcessInfo proc, MemoryFeatures features,
|
||
BaselineResult baseline, List<SignatureMatch> matches, string reasoning)
|
||
{
|
||
return new ScanResult
|
||
{
|
||
Pid = proc.Pid,
|
||
ProcessName = proc.Name,
|
||
RiskLevel = RiskLevel.Safe,
|
||
RiskScore = Math.Min(baseline.AnomalyScore, 0.15),
|
||
Indicators = new List<string>(),
|
||
Reasoning = reasoning,
|
||
Matches = matches,
|
||
AIProvider = "pipeline-v2/baseline",
|
||
DetectionLayer = "Layer1_Baseline",
|
||
ScanTime = DateTime.Now
|
||
};
|
||
}
|
||
|
||
private static List<string> BuildIndicators(MemoryFeatures f, BaselineResult baseline,
|
||
ClassificationResult classification, RuleValidationResult rule)
|
||
{
|
||
var indicators = new List<string>();
|
||
|
||
if (baseline.IsAnomalous)
|
||
{
|
||
indicators.Add($"基线异常(分数={baseline.AnomalyScore:F2})");
|
||
foreach (var idx in baseline.DeviantFeatureIndices.Take(3))
|
||
indicators.Add($"偏离特征#{idx}");
|
||
}
|
||
|
||
if (classification.Classification == MalwareClass.Malicious)
|
||
indicators.Add($"AI分类:恶意({classification.SuspectedFamily})");
|
||
else if (classification.Classification == MalwareClass.Suspicious)
|
||
indicators.Add("AI分类:可疑");
|
||
|
||
if (rule.MatchedRuleCount > 0)
|
||
{
|
||
foreach (var tech in rule.MatchedTechniques.Take(5))
|
||
indicators.Add(tech);
|
||
}
|
||
|
||
if (f.RwxPrivatePages > 0)
|
||
indicators.Add($"RWX私有页={f.RwxPrivatePages}");
|
||
|
||
if (f.PeMismatchDisk)
|
||
indicators.Add("ProcessHollowing");
|
||
|
||
if (f.SuspiciousStringHits > 0)
|
||
indicators.Add($"敏感字符串={f.SuspiciousStringHits}");
|
||
|
||
return indicators;
|
||
}
|
||
|
||
private static string DetermineDetectionLayer(BaselineResult baseline,
|
||
ClassificationResult classification, RuleValidationResult rule)
|
||
{
|
||
if (rule.MatchedRuleCount >= 2) return "L3_Rules+L2_AI+L1_Baseline";
|
||
if (classification.Classification == MalwareClass.Malicious) return "L2_AI+L1_Baseline";
|
||
if (baseline.IsAnomalous) return "L1_Baseline";
|
||
return "PreFilter";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扫描模式
|
||
/// </summary>
|
||
public enum ScanMode
|
||
{
|
||
/// <summary>快速模式:仅元数据,不读取内存</summary>
|
||
Fast,
|
||
|
||
/// <summary>平衡模式:采样熵值 + 特征提取</summary>
|
||
Balanced,
|
||
|
||
/// <summary>深度模式:全量内存扫描 + 完整特征提取</summary>
|
||
Deep
|
||
}
|