public sealed class PeAnalysisService : IPeAnalysisService
{
private readonly IPeParser _parser;
private readonly IPeValidator _validator;
private readonly PeAnalysisOrchestrator _analysisOrchestrator;
private readonly IPeCacheService _cache;
private readonly ContentHasher _hasher;
private readonly PeAnalysisOptions _options;
public PeAnalysisService(
IPeParser parser,
IPeValidator validator,
PeAnalysisOrchestrator analysisOrchestrator,
IPeCacheService cache,
ContentHasher hasher,
IOptions<PeAnalysisOptions> options)
{
_parser = parser;
_validator = validator;
_analysisOrchestrator = analysisOrchestrator;
_cache = cache;
_hasher = hasher;
_options = options.Value;
}
public async Task<PeImageInfo> GetOrParseAsync(Stream stream, CancellationToken cancellationToken = default)
{
var hash = await _hasher.ComputeSha256Async(stream, cancellationToken).ConfigureAwait(false);
var key = CacheKeyGenerator.ForPeImage(hash);
return await _cache.GetOrCreateAsync(key, ct => _parser.ParseAsync(stream, ct), cancellationToken).ConfigureAwait(false);
}
public async Task<PeAnalysisResult> AnalyzeAsync(Stream stream, CancellationToken cancellationToken = default)
{
var pe = await GetOrParseAsync(stream, cancellationToken).ConfigureAwait(false);
var validations = await _validator.ValidateAsync(pe, cancellationToken).ConfigureAwait(false);
var findings = await _analysisOrchestrator.AnalyzeAsync(pe, cancellationToken).ConfigureAwait(false);
var family = findings.Any(f =>
f.Title.Contains("shellcode", StringComparison.OrdinalIgnoreCase))
? ExecutableFamily.Shellcode
: pe.Family;
var detection = new ExecutableDetectionResult(family, 0.8, pe.Warnings);
return new PeAnalysisResult(pe, validations, findings, detection);
}
}