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
|
|||
|
|
}
|