// DefenderRuleParser // Author: Andrea Cristaldi 2025 - https://github.com/andreacristaldi/DefenderRuleParser // This project is licensed under the Apache 2.0 License. /* * Summary: Parses embedded LUA-like script fragments when present. * Origin: dump-driven; string/range harvesting from observed script chunks. * Role: Surfaces script markers and literals for intel. */ using DefenderRuleParser2; using DefenderRuleParser2.Models; using System; using System.IO; using System.Text; using System.Collections.Generic; namespace DefenderRuleParser2.Parsers { public class LuaParser : ISignatureParser { private static readonly byte[] LuaHeader = new byte[] { 0x1B, 0x4C, 0x75, 0x61 }; public void Parse(BinaryReader reader, int size, uint threatId) { long offset = reader.BaseStream.Position; try { byte[] buffer = reader.ReadBytes(size); int headerIndex = FindLuaHeader(buffer); if (headerIndex == -1) { Logger.Info($"[LUA] Threat ID: {threatId} | Lua header not found."); return; } byte[] luaCode = new byte[buffer.Length - headerIndex]; Array.Copy(buffer, headerIndex, luaCode, 0, luaCode.Length); string luaPath = Logger.OutputFolder + $"lua_script_{threatId}.lua"; File.WriteAllBytes(luaPath, luaCode); Logger.Info($"[LUA] Threat ID: {threatId} | Extracted Lua script to: {luaPath}"); if (ThreatDatabase.TryGetThreat(threatId, out var threat)) { threat.Signatures.Add(new SignatureEntry { Type = "SIGNATURE_TYPE_LUASTANDALONE", Offset = offset, Pattern = new List { $"Extracted: {luaPath}" }, Parsed = true, ConditionType = "PRESENT", ConditionValue = 1 }); } } catch (Exception ex) { Logger.Error($"[LUA] Error parsing at offset 0x{offset:X}: {ex.Message}"); } finally { reader.BaseStream.Seek(offset + size, SeekOrigin.Begin); } } private int FindLuaHeader(byte[] data) { for (int i = 0; i <= data.Length - LuaHeader.Length; i++) { bool match = true; for (int j = 0; j < LuaHeader.Length; j++) { if (data[i + j] != LuaHeader[j]) { match = false; break; } } if (match) return i; } return -1; } } }