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

176 lines
5.8 KiB
C#
Raw 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>
/// 无监督基线检测引擎 —— 第一层过滤
/// 使用统计异常检测方法Z-score + 重构误差),无需恶意样本训练
/// 核心逻辑:正常程序内存结构高度规整,恶意程序偏离基线
/// </summary>
public class BaselineEngine
{
private readonly BaselineLibrary _baselineLibrary;
private readonly double _globalAnomalyThreshold;
public BaselineEngine(BaselineLibrary? library = null, double threshold = 0.50)
{
_baselineLibrary = library ?? BaselineLibrary.CreateDefault();
_globalAnomalyThreshold = threshold;
}
/// <summary>
/// 分析进程特征,返回异常分数和判定结果
/// </summary>
public BaselineResult Analyze(MemoryFeatures features)
{
var result = new BaselineResult();
// 1. 找到最匹配的基线
var baseline = _baselineLibrary.FindBestMatch(features.ProcessName, features.ExePath);
if (baseline == null)
{
result.IsAnomalous = false;
result.AnomalyScore = 0;
result.Details = "无匹配基线,跳过异常检测";
return result;
}
result.BaselineName = baseline.Name;
// 2. 转换特征为向量
var featureVector = features.ToFeatureVector();
// 3. 计算 Z-score 异常分数 (Mahalanobis-like)
var (anomalyScore, deviantFeatures) = baseline.CalculateAnomalyScore(featureVector);
// 4. 计算重构误差
var reconstructionError = baseline.CalculateReconstructionError(featureVector);
// 5. 综合分数Z-score 异常 + 重构误差加权
var combinedScore = anomalyScore * 0.6 + reconstructionError * 0.4;
combinedScore = Math.Min(combinedScore, 1.0);
result.AnomalyScore = combinedScore;
result.DeviantFeatureCount = deviantFeatures.Count;
result.DeviantFeatureIndices = deviantFeatures;
result.ReconstructionError = reconstructionError;
result.IsAnomalous = combinedScore > _globalAnomalyThreshold;
// 6. 生成可解释性说明
result.Details = GenerateExplanation(features, baseline, deviantFeatures, combinedScore);
// 7. 判定分类
result.Classification = combinedScore switch
{
< 0.25 => BaselineClassification.Normal,
< 0.50 => BaselineClassification.BenignVariance,
< 0.75 => BaselineClassification.Anomalous,
_ => BaselineClassification.HighlyAnomalous
};
return result;
}
/// <summary>
/// 快速预判 —— 仅基于元数据,不读内存
/// </summary>
public BaselineResult QuickPreAnalyze(ProcessInfo proc, List<MemoryRegion> regions)
{
var extractor = new FeatureExtractor();
var features = extractor.QuickExtract(proc, regions);
return Analyze(features);
}
private static string GenerateExplanation(MemoryFeatures f, BaselineProfile baseline,
List<int> deviantFeatures, double score)
{
var parts = new List<string>();
if (score < 0.25)
{
parts.Add("进程内存结构符合正常程序基线");
return string.Join("; ", parts);
}
// 命名特征索引对应的含义
var featureNames = new Dictionary<int, string>
{
{0, "未签名"}, {1, "非系统路径"}, {2, "临时路径"},
{5, "系统进程名"}, {6, "父进程异常"},
{12, "RWX页比例高"}, {13, "匿名可执行页"}, {14, "RWX私有页"},
{18, "内存PE头"}, {19, "PE与磁盘不一致"},
{20, "可疑API"}, {21, "敏感字符串"}, {22, "签名匹配"}, {23, "高危签名"},
{24, "高熵代码段"}, {25, "最大熵值"}, {26, "高熵区域数"},
{29, "非标准端口连接"}, {30, "可疑端口"}, {31, "境外连接"},
{35, "无磁盘映射模块"}, {36, "临时目录模块"}
};
foreach (var idx in deviantFeatures.Take(5))
{
if (featureNames.TryGetValue(idx, out var name))
parts.Add(name);
}
parts.Add($"异常分数={score:F2}");
if (f.RwxPrivatePages > 0 && f.IsSystemProcessName)
parts.Insert(0, "严重警告: 系统进程存在RWX私有内存");
if (f.PeMismatchDisk)
parts.Insert(0, "严重警告: Process Hollowing 检测");
return string.Join("; ", parts);
}
}
/// <summary>
/// 基线检测结果
/// </summary>
public class BaselineResult
{
/// <summary>使用的基线名称</summary>
public string BaselineName { get; set; } = "";
/// <summary>综合异常分数 [0-1]</summary>
public double AnomalyScore { get; set; }
/// <summary>是否判定为异常</summary>
public bool IsAnomalous { get; set; }
/// <summary>偏离特征数量</summary>
public int DeviantFeatureCount { get; set; }
/// <summary>偏离特征索引列表</summary>
public List<int> DeviantFeatureIndices { get; set; } = new();
/// <summary>重构误差</summary>
public double ReconstructionError { get; set; }
/// <summary>分类结果</summary>
public BaselineClassification Classification { get; set; }
/// <summary>可解释性详情</summary>
public string Details { get; set; } = "";
}
/// <summary>
/// 基线分类结果
/// </summary>
public enum BaselineClassification
{
/// <summary>完全正常</summary>
Normal,
/// <summary>良性偏差(如开发工具、安全软件的正常表现)</summary>
BenignVariance,
/// <summary>异常偏离基线</summary>
Anomalous,
/// <summary>高度异常</summary>
HighlyAnomalous
}