save progress

This commit is contained in:
StellaOps Bot
2026-01-06 09:42:02 +02:00
parent 94d68bee8b
commit 37e11918e0
443 changed files with 85863 additions and 897 deletions

View File

@@ -7,6 +7,7 @@ using System.Security.Cryptography;
using Microsoft.Extensions.Logging;
using StellaOps.BinaryIndex.Disassembly;
using StellaOps.BinaryIndex.Normalization;
using StellaOps.BinaryIndex.Semantic;
namespace StellaOps.BinaryIndex.DeltaSig;
@@ -17,18 +18,49 @@ public sealed class DeltaSignatureGenerator : IDeltaSignatureGenerator
{
private readonly DisassemblyService _disassemblyService;
private readonly NormalizationService _normalizationService;
private readonly IIrLiftingService? _irLiftingService;
private readonly ISemanticGraphExtractor? _graphExtractor;
private readonly ISemanticFingerprintGenerator? _fingerprintGenerator;
private readonly ILogger<DeltaSignatureGenerator> _logger;
/// <summary>
/// Creates a new delta signature generator without semantic analysis support.
/// </summary>
public DeltaSignatureGenerator(
DisassemblyService disassemblyService,
NormalizationService normalizationService,
ILogger<DeltaSignatureGenerator> logger)
: this(disassemblyService, normalizationService, null, null, null, logger)
{
_disassemblyService = disassemblyService;
_normalizationService = normalizationService;
_logger = logger;
}
/// <summary>
/// Creates a new delta signature generator with optional semantic analysis support.
/// </summary>
public DeltaSignatureGenerator(
DisassemblyService disassemblyService,
NormalizationService normalizationService,
IIrLiftingService? irLiftingService,
ISemanticGraphExtractor? graphExtractor,
ISemanticFingerprintGenerator? fingerprintGenerator,
ILogger<DeltaSignatureGenerator> logger)
{
_disassemblyService = disassemblyService ?? throw new ArgumentNullException(nameof(disassemblyService));
_normalizationService = normalizationService ?? throw new ArgumentNullException(nameof(normalizationService));
_irLiftingService = irLiftingService;
_graphExtractor = graphExtractor;
_fingerprintGenerator = fingerprintGenerator;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// Gets a value indicating whether semantic analysis is available.
/// </summary>
public bool SemanticAnalysisAvailable =>
_irLiftingService is not null &&
_graphExtractor is not null &&
_fingerprintGenerator is not null;
/// <inheritdoc />
public async Task<DeltaSignature> GenerateSignaturesAsync(
Stream binaryStream,
@@ -94,11 +126,14 @@ public sealed class DeltaSignatureGenerator : IDeltaSignatureGenerator
}
// Generate signature from normalized bytes
var signature = GenerateSymbolSignature(
var signature = await GenerateSymbolSignatureAsync(
normalized,
symbolName,
symbolInfo.Section ?? ".text",
options);
instructions,
binary.Architecture,
options,
ct);
symbolSignatures.Add(signature);
@@ -218,6 +253,136 @@ public sealed class DeltaSignatureGenerator : IDeltaSignatureGenerator
};
}
/// <inheritdoc />
public async Task<SymbolSignature> GenerateSymbolSignatureAsync(
NormalizedFunction normalized,
string symbolName,
string scope,
IReadOnlyList<DisassembledInstruction> originalInstructions,
CpuArchitecture architecture,
SignatureOptions? options = null,
CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(normalized);
ArgumentNullException.ThrowIfNull(symbolName);
ArgumentNullException.ThrowIfNull(scope);
ArgumentNullException.ThrowIfNull(originalInstructions);
options ??= new SignatureOptions();
// Get normalized bytes for hashing
var normalizedBytes = GetNormalizedBytes(normalized);
// Compute the main hash
var hashHex = ComputeHash(normalizedBytes, options.HashAlgorithm);
// Compute chunk hashes for resilience
ImmutableArray<ChunkHash>? chunks = null;
if (options.IncludeChunks && normalizedBytes.Length >= options.ChunkSize)
{
chunks = ComputeChunkHashes(normalizedBytes, options.ChunkSize, options.HashAlgorithm);
}
// Compute CFG metrics using proper CFG analysis
int? bbCount = null;
string? cfgEdgeHash = null;
if (options.IncludeCfg && normalized.Instructions.Length > 0)
{
// Use first instruction's address as start address
var startAddress = normalized.Instructions[0].OriginalAddress;
var cfgMetrics = CfgExtractor.ComputeMetrics(
normalized.Instructions.ToList(),
startAddress);
bbCount = cfgMetrics.BasicBlockCount;
cfgEdgeHash = cfgMetrics.EdgeHash;
}
// Compute semantic fingerprint if enabled and services available
string? semanticHashHex = null;
ImmutableArray<string>? semanticApiCalls = null;
if (options.IncludeSemantic && SemanticAnalysisAvailable && originalInstructions.Count > 0)
{
try
{
var semanticFingerprint = await ComputeSemanticFingerprintAsync(
originalInstructions,
symbolName,
architecture,
ct);
if (semanticFingerprint is not null)
{
semanticHashHex = semanticFingerprint.GraphHashHex;
semanticApiCalls = semanticFingerprint.ApiCalls;
}
}
catch (Exception ex)
{
_logger.LogWarning(
ex,
"Failed to compute semantic fingerprint for {Symbol}, continuing without semantic data",
symbolName);
}
}
return new SymbolSignature
{
Name = symbolName,
Scope = scope,
HashAlg = options.HashAlgorithm,
HashHex = hashHex,
SizeBytes = normalizedBytes.Length,
CfgBbCount = bbCount,
CfgEdgeHash = cfgEdgeHash,
Chunks = chunks,
SemanticHashHex = semanticHashHex,
SemanticApiCalls = semanticApiCalls
};
}
private async Task<SemanticFingerprint?> ComputeSemanticFingerprintAsync(
IReadOnlyList<DisassembledInstruction> instructions,
string functionName,
CpuArchitecture architecture,
CancellationToken ct)
{
if (_irLiftingService is null || _graphExtractor is null || _fingerprintGenerator is null)
{
return null;
}
// Check if architecture is supported
if (!_irLiftingService.SupportsArchitecture(architecture))
{
_logger.LogDebug(
"Architecture {Arch} not supported for semantic analysis",
architecture);
return null;
}
// Lift to IR
var startAddress = instructions.Count > 0 ? instructions[0].Address : 0UL;
var lifted = await _irLiftingService.LiftToIrAsync(
instructions,
functionName,
startAddress,
architecture,
ct: ct);
// Extract semantic graph
var graph = await _graphExtractor.ExtractGraphAsync(lifted, ct: ct);
// Generate fingerprint
var fingerprint = await _fingerprintGenerator.GenerateAsync(
graph,
startAddress,
ct: ct);
return fingerprint;
}
private static byte[] GetNormalizedBytes(NormalizedFunction normalized)
{
// Concatenate all normalized instruction bytes