mirror of
https://github.com/andreacristaldi/DefenderRuleParser
synced 2026-06-16 13:55:00 +00:00
118 lines
5.4 KiB
C#
118 lines
5.4 KiB
C#
// DefenderRuleParser
|
||
// Author: Andrea Cristaldi 2025 - https://github.com/andreacristaldi/DefenderRuleParser
|
||
// This project is licensed under the Apache 2.0 License.
|
||
using System;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using DefenderRuleParser2.Models;
|
||
|
||
namespace DefenderRuleParser2
|
||
{
|
||
public static class SignatureReader
|
||
{
|
||
public static void ExtractSignatures(BinaryReader reader, string filePath)
|
||
{
|
||
long fileLength = reader.BaseStream.Length;
|
||
uint currentThreatId = 0;
|
||
|
||
while (reader.BaseStream.Position < fileLength)
|
||
{
|
||
long position = reader.BaseStream.Position;
|
||
|
||
try
|
||
{
|
||
byte typeByte = reader.ReadByte();
|
||
byte sizeLow = reader.ReadByte();
|
||
ushort sizeHigh = reader.ReadUInt16();
|
||
int size = sizeLow + (sizeHigh << 8);
|
||
|
||
|
||
string sigType = SignatureTypeMapper.GetSignatureType(typeByte);
|
||
long endPosition = reader.BaseStream.Position + size;
|
||
|
||
//debug
|
||
|
||
long signatureStart = position;
|
||
long dataStart = reader.BaseStream.Position;
|
||
byte[] signatureData = reader.ReadBytes(size);
|
||
byte sizeHighLo = (byte)(sizeHigh & 0xFF);
|
||
byte sizeHighHi = (byte)((sizeHigh >> 8) & 0xFF);
|
||
Logger.Verbose($"\n[HDR] type=0x{typeByte:X2} ({typeByte}) sizeLow=0x{sizeLow:X2} sizeHigh=0x{sizeHigh:X4} -> size={size}");
|
||
Logger.Verbose($"[HDR-HEX] @0x{position:X}: {typeByte:X2} {sizeLow:X2} {sizeHighLo:X2} {sizeHighHi:X2}");
|
||
Logger.HexDumpVerbose($"[DBG] Signature at 0x{signatureStart:X} ({sigType}) - Size: {size} bytes", signatureData, signatureStart + (dataStart - signatureStart));
|
||
reader.BaseStream.Seek(dataStart, SeekOrigin.Begin);
|
||
|
||
|
||
|
||
Console.WriteLine($"[>] Found signature: {sigType} @0x{position:X}, Size: {size}");
|
||
|
||
if (sigType == "SIGNATURE_TYPE_THREAT_BEGIN")
|
||
{
|
||
// payload THREAT_BEGIN
|
||
currentThreatId = reader.ReadUInt32(); // primi 4 byte = ThreatID
|
||
var threat = ThreatDatabase.CreateOrUpdateThreat(currentThreatId, position);
|
||
|
||
Logger.Info($"[+] Threat Begin: ID={currentThreatId} Name='{threat.ThreatName}'");
|
||
|
||
// Se il record ha metadati extra oltre ai 4 byte dell’ID, saltali ora:
|
||
long consumed = reader.BaseStream.Position - (position + 4); // normalmente 0
|
||
long remainingInThisRecord = endPosition - reader.BaseStream.Position;
|
||
if (remainingInThisRecord > 0)
|
||
{
|
||
// opzionale: fai un dump per capire che c’è dentro
|
||
// byte[] meta = reader.ReadBytes((int)remainingInThisRecord);
|
||
// HexDumper.Print("[DBG] ThreatBegin extra", meta, reader.BaseStream.Position - meta.Length);
|
||
reader.BaseStream.Seek(remainingInThisRecord, SeekOrigin.Current);
|
||
}
|
||
|
||
// Fine: il prossimo ReadByte() del while esterno vedrà il type del record successivo
|
||
}
|
||
else if (sigType == "SIGNATURE_TYPE_THREAT_END")
|
||
{
|
||
uint endThreatId = reader.ReadUInt32();
|
||
if (ThreatDatabase.TryUpdateThreatEnd(endThreatId, endPosition))
|
||
|
||
Logger.Info($"[✓] Threat End: ID={endThreatId} @0x{endPosition:X}");
|
||
|
||
// Se esistono extra (di solito no), salta comunque al termine del record
|
||
long left = endPosition - reader.BaseStream.Position;
|
||
if (left > 0) reader.BaseStream.Seek(left, SeekOrigin.Current);
|
||
}
|
||
else if (sigType != "SIGNATURE_TYPE_UNKNOWN")
|
||
{
|
||
SignatureDispatcher.Dispatch(sigType, reader, size, currentThreatId);
|
||
}
|
||
|
||
|
||
|
||
// Allineamento sicuro
|
||
if (reader.BaseStream.Position < endPosition)
|
||
{
|
||
long remaining = endPosition - reader.BaseStream.Position;
|
||
|
||
Logger.Warn($"[~] Skipping {remaining} byte(s) to align with next signature...");
|
||
|
||
reader.BaseStream.Seek(remaining, SeekOrigin.Current);
|
||
}
|
||
|
||
Debug.Assert(reader.BaseStream.Position == endPosition,
|
||
$"[ASSERT] Parser per {sigType} ha letto {reader.BaseStream.Position - position} byte, " +
|
||
$"previsti {endPosition - position}");
|
||
}
|
||
catch (EndOfStreamException)
|
||
{
|
||
Logger.Warn("[!] Reached unexpected end of stream.");
|
||
break;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Logger.Error($"[!] Exception at 0x{position:X}: {ex.Message}");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|