public EventRecord(BinaryReader recordData, int recordPosition, ChunkInfo chunk) { var l = LogManager.GetLogger("EventRecord"); RecordPosition = recordPosition; ChunkNumber = chunk.ChunkNumber; recordData.ReadInt32(); //signature Size = recordData.ReadUInt32(); RecordNumber = recordData.ReadInt64(); Timestamp = DateTimeOffset.FromFileTime(recordData.ReadInt64()).ToUniversalTime(); if (recordData.PeekChar() != 0xf) { throw new Exception("Payload does not start with 0x1f!"); } l.Trace( $"Record position: 0x{RecordPosition:X4} Record #: {RecordNumber.ToString().PadRight(3)} Timestamp: {Timestamp:yyyy-MM-dd HH:mm:ss.fffffff}"); Nodes = new List <IBinXml>(); var eof = false; while (eof == false) { var nextTag = TagBuilder.BuildTag(recordPosition, recordData, chunk); Nodes.Add(nextTag); if (nextTag is EndOfBXmlStream) //nothing left to do, so exit { eof = true; } } BuildProperties(); }
public EventRecord(BinaryReader recordData, int recordPosition, ChunkInfo chunk) { var l = LogManager.GetLogger("EventRecord"); RecordPosition = recordPosition; ChunkNumber = chunk.ChunkNumber; recordData.ReadInt32(); //signature Size = recordData.ReadUInt32(); RecordNumber = recordData.ReadInt64(); Timestamp = DateTimeOffset.FromFileTime(recordData.ReadInt64()).ToUniversalTime(); if (recordData.PeekChar() != 0xf) { throw new Exception("Payload does not start with 0x1f!"); } l.Trace( $"\r\nRecord position: 0x{RecordPosition:X4} Record #: {RecordNumber.ToString().PadRight(3)} Timestamp: {Timestamp:yyyy-MM-dd HH:mm:ss.fffffff}"); Nodes = new List <IBinXml>(); var eof = false; while (eof == false) { var nextTag = TagBuilder.BuildTag(recordPosition, recordData, chunk); Nodes.Add(nextTag); if (nextTag is EndOfBXmlStream) { //nothing left to do, so exit eof = true; //check here if there is a 0x2a0x2a and if so, another record! var found2a = true; //danderspritz test var maxCount = 0; while (recordData.ReadByte() != 0x2a && maxCount < 15) { if (recordData.BaseStream.Position == recordData.BaseStream.Length) { found2a = false; break; //out of data } maxCount += 1; } if (found2a) { //a secondary check to eliminate false positives if (recordData.ReadByte() == 0x2a) { //back up two recordData.BaseStream.Seek(-2, SeekOrigin.Current); ExtraDataOffset = recordData.BaseStream.Position; } } } } BuildProperties(); }
public EventLog(Stream fileStream) { const long eventSignature = 0x00656c6946666c45; const long chunkSignature = 0x6B6E6843666C45; var headerBytes = new byte[4096]; fileStream.Read(headerBytes, 0, 4096); if (BitConverter.ToInt64(headerBytes, 0) != eventSignature) { throw new Exception("Invalid signature! Expected 'ElfFile'"); } FirstChunkNumber = BitConverter.ToInt64(headerBytes, 0x8); LastChunkNumber = BitConverter.ToInt64(headerBytes, 0x10); NextRecordId = BitConverter.ToInt64(headerBytes, 0x18); var unusedSize = BitConverter.ToInt32(headerBytes, 0x20); MinorVersion = BitConverter.ToInt16(headerBytes, 0x24); MajorVersion = BitConverter.ToInt16(headerBytes, 0x26); var unusedHeaderSize = BitConverter.ToInt16(headerBytes, 0x28); ChunkCount = BitConverter.ToInt16(headerBytes, 0x2A); Flags = (EventLogFlag)BitConverter.ToInt32(headerBytes, 0x78); Crc = BitConverter.ToInt32(headerBytes, 0x7C); var inputArray = new byte[120 + 4]; Buffer.BlockCopy(headerBytes, 0, inputArray, 0, 120); Crc32Algorithm.ComputeAndWriteToEnd(inputArray); // last 4 bytes contains CRC CalculatedCrc = BitConverter.ToInt32(inputArray, inputArray.Length - 4); //we are at offset 0x1000 and ready to start //chunk size == 65536, or 0x10000 var chunkBuffer = new byte[0x10000]; Chunks = new List <ChunkInfo>(); var chunkOffset = fileStream.Position; var bytesRead = fileStream.Read(chunkBuffer, 0, 0x10000); EventIdMetrics = new Dictionary <long, int>(); Logger.Trace($"Event Log data before processing chunks:\r\n{this}"); var chunkNumber = 0; while (bytesRead > 0) { var chunkSig = BitConverter.ToInt64(chunkBuffer, 0); Logger.Trace( $"chunk offset: 0x{chunkOffset:X}, sig: {Encoding.ASCII.GetString(chunkBuffer, 0, 8)} signature val: 0x{chunkSig:X}"); if (chunkSig == chunkSignature) { var ci = new ChunkInfo(chunkBuffer, chunkOffset, chunkNumber); Chunks.Add(ci); TotalEventLogs += ci.EventRecords.Count; } else { Logger.Trace($"Skipping chunk at 0x{chunkOffset:X} as it does not have correct signature"); } chunkOffset = fileStream.Position; bytesRead = fileStream.Read(chunkBuffer, 0, 0x10000); chunkNumber += 1; } ErrorRecords = new Dictionary <long, string>(); foreach (var chunkInfo in Chunks) { foreach (var eventIdMetric in chunkInfo.EventIdMetrics) { if (EventIdMetrics.ContainsKey(eventIdMetric.Key) == false) { EventIdMetrics.Add(eventIdMetric.Key, 0); } EventIdMetrics[eventIdMetric.Key] += eventIdMetric.Value; } foreach (var chunkInfoErrorRecord in chunkInfo.ErrorRecords) { ErrorRecords.Add(chunkInfoErrorRecord.Key, chunkInfoErrorRecord.Value); } } }
public IEnumerable <EventRecord> GetEventRecords() { //we are at offset 0x1000 and ready to start //chunk size == 65536, or 0x10000 var chunkBuffer = new byte[0x10000]; var chunkOffset = _stream.Position; var bytesRead = _stream.Read(chunkBuffer, 0, 0x10000); EventIdMetrics = new Dictionary <long, int>(); var chunkNumber = 0; while (bytesRead > 0) { var chunkSig = BitConverter.ToInt64(chunkBuffer, 0); Logger.Debug($"Processing chunk at offset 0x{chunkOffset:X}. Events found so far: {TotalEventLogs:N0}"); if (chunkSig == ChunkSignature) { var ci = new ChunkInfo(chunkBuffer, chunkOffset, chunkNumber); foreach (var er in ci.EventRecords) { if (EarliestTimestamp == null) { EarliestTimestamp = er.Timestamp; } else { if (er.Timestamp.Ticks < EarliestTimestamp.Value.Ticks) { EarliestTimestamp = er.Timestamp; } } if (LatestTimestamp == null) { LatestTimestamp = er.Timestamp; } else { if (er.Timestamp.Ticks > LatestTimestamp.Value.Ticks) { LatestTimestamp = er.Timestamp; } } if (EventIdMetrics.ContainsKey(er.EventId) == false) { EventIdMetrics.Add(er.EventId, 0); } EventIdMetrics[er.EventId] += 1; yield return(er); } foreach (var chunkInfoErrorRecord in ci.ErrorRecords) { ErrorRecords.Add(chunkInfoErrorRecord.Key, chunkInfoErrorRecord.Value); } TotalEventLogs += ci.EventRecords.Count; } else { Logger.Trace($"Skipping chunk at 0x{chunkOffset:X} as it does not have correct signature"); } chunkOffset = _stream.Position; bytesRead = _stream.Read(chunkBuffer, 0, 0x10000); chunkNumber += 1; } }
public EventRecord(BinaryReader recordData, int recordPosition, ChunkInfo chunk) { var l = LogManager.GetLogger("EventRecord"); RecordPosition = recordPosition; recordData.ReadInt32(); //signature Size = recordData.ReadUInt32(); RecordNumber = recordData.ReadInt64(); Timestamp = DateTimeOffset.FromFileTime(recordData.ReadInt64()).ToUniversalTime(); if (recordData.PeekChar() != 0xf) { throw new Exception("Payload does not start with 0x1f!"); } l.Trace( $"Record position: 0x{RecordPosition:X4} Record #: {RecordNumber.ToString().PadRight(3)} Timestamp: {Timestamp:yyyy-MM-dd HH:mm:ss.fffffff}"); Nodes = new List <IBinXml>(); var eof = false; while (eof == false) { var nextTag = TagBuilder.BuildTag(recordPosition, recordData, chunk); Nodes.Add(nextTag); if (nextTag is EndOfBXmlStream) //nothing left to do, so exit { eof = true; } } var xml = ConvertPayloadToXml(); using (var sr = new StringReader(xml)) { var docNav = new XPathDocument(sr); var nav = docNav.CreateNavigator(); var computer = nav.SelectSingleNode(@"/Event/System/Computer"); var channel = nav.SelectSingleNode(@"/Event/System/Channel"); var eventRecordId = nav.SelectSingleNode(@"/Event/System/EventRecordID"); var eventId = nav.SelectSingleNode(@"/Event/System/EventID"); var level = nav.SelectSingleNode(@"/Event/System/Level"); var timeCreated = nav.SelectSingleNode(@"/Event/System/TimeCreated")?.GetAttribute("SystemTime", ""); var provider = nav.SelectSingleNode(@"/Event/System/Provider")?.GetAttribute("Name", ""); var processId = nav.SelectSingleNode(@"/Event/System/Execution")?.GetAttribute("ProcessID", ""); var threadId = nav.SelectSingleNode(@"/Event/System/Execution")?.GetAttribute("ThreadID", ""); var userId = nav.SelectSingleNode(@"/Event/System/Security")?.GetAttribute("UserID", ""); TimeCreated = DateTimeOffset.Parse(timeCreated, null, DateTimeStyles.AssumeUniversal).ToUniversalTime(); if (eventId != null) { EventId = eventId.ValueAsInt; } //if (level != null) //{ // Level = level.ValueAsInt; //} //if (eventRecordId != null) //{ // EventRecordId = eventRecordId.Value; //} //if (processId != null) //{ // ProcessId = int.Parse(processId); //} //if (threadId != null) //{ // ThreadId = int.Parse(threadId); //} var payloadNode = nav.SelectSingleNode(@"/Event/EventData"); if (payloadNode == null) { payloadNode = nav.SelectSingleNode(@"/Event/UserData"); } var payloadXml = payloadNode?.OuterXml; //if (EventLog.EventLogMaps.ContainsKey($"{EventId}-{channel.ToString().ToUpperInvariant()}")) //{ // l.Trace($"Found map for event id {EventId} with Channel '{channel}'!"); // var map = EventLog.EventLogMaps[$"{EventId}-{channel.ToString().ToUpperInvariant()}"]; // MapDescription = map.Description; // foreach (var mapEntry in map.Maps) // { // var valProps = new Dictionary<string, string>(); // foreach (var me in mapEntry.Values) // { // //xpath out variables // var propVal = nav.SelectSingleNode(me.Value); // if (propVal != null) // { // var propValue = propVal.Value; // if (me.Refine.IsNullOrEmpty() == false) // { // var hits = new List<string>(); // //regex time // MatchCollection allMatchResults = null; // try { // Regex regexObj = new Regex(me.Refine, RegexOptions.IgnoreCase); // allMatchResults = regexObj.Matches(propValue); // if (allMatchResults.Count > 0) { // // Access individual matches using allMatchResults.Item[] // foreach (Match allMatchResult in allMatchResults) // { // hits.Add(allMatchResult.Value); // } // propValue = string.Join(" | ", hits); // } // } catch (ArgumentException ) { // // Syntax error in the regular expression // } // } // valProps.Add(me.Name, propValue); // } // else // { // valProps.Add(me.Name, string.Empty); // l.Warn( // $"Record # {RecordNumber} (Event Record Id: {EventRecordId}): In map for event '{map.EventId}', Property '{me.Value}' not found! Replacing with empty string"); // } // } // //we have the values, now substitute // var propertyValue = mapEntry.PropertyValue; // foreach (var valProp in valProps) // { // propertyValue = propertyValue.Replace($"%{valProp.Key}%", valProp.Value); // } // var propertyToUpdate = mapEntry.Property.ToUpperInvariant(); // if (valProps.Count == 0) // { // propertyToUpdate = "NOMATCH"; //prevents variables from showing up in the CSV // } // //we should now have our new value, so stick it in its place // switch (propertyToUpdate) // { // case "USERNAME": // UserName = propertyValue; // break; // case "REMOTEHOST": // RemoteHost = propertyValue; // break; // case "EXECUTABLEINFO": // ExecutableInfo = propertyValue; // break; // case "PAYLOADDATA1": // PayloadData1 = propertyValue; // break; // case "PAYLOADDATA2": // PayloadData2 = propertyValue; // break; // case "PAYLOADDATA3": // PayloadData3 = propertyValue; // break; // case "PAYLOADDATA4": // PayloadData4 = propertyValue; // break; // case "PAYLOADDATA5": // PayloadData5 = propertyValue; // break; // case "PAYLOADDATA6": // PayloadData6 = propertyValue; // break; // case "NOMATCH": // //when a property was not found. // break; // default: // l.Warn( // $"Unknown property name '{propertyToUpdate}'! Dropping mapping value of '{propertyValue}'"); // break; //} //sanity checks //UserId = userId ?? string.Empty; Provider = provider ?? string.Empty; Channel = channel?.Value ?? string.Empty; Computer = computer?.Value ?? string.Empty; Payload = payloadXml ?? string.Empty; } }
public EventRecord(BinaryReader recordData, int recordPosition, ChunkInfo chunk) { var l = LogManager.GetLogger("EventRecord"); RecordPosition = recordPosition; recordData.ReadInt32(); //signature Size = recordData.ReadUInt32(); RecordNumber = recordData.ReadInt64(); Timestamp = DateTimeOffset.FromFileTime(recordData.ReadInt64()).ToUniversalTime(); if (recordData.PeekChar() != 0xf) { throw new Exception("Payload does not start with 0x1f!"); } l.Trace( $"Record position: 0x{RecordPosition:X4} Record #: {RecordNumber.ToString().PadRight(3)} Timestamp: {Timestamp:yyyy-MM-dd HH:mm:ss.fffffff}"); Nodes = new List <IBinXml>(); var eof = false; while (eof == false) { var nextTag = TagBuilder.BuildTag(recordPosition, recordData, chunk); Nodes.Add(nextTag); if (nextTag is EndOfBXmlStream) //nothing left to do, so exit { eof = true; } } var xml = ConvertPayloadToXml(); xml = xml.Replace(" xmlns=\"http://schemas.microsoft.com/win/2004/08/events/event\"", ""); using (var sr = new StringReader(xml)) { var docNav = new XPathDocument(sr); var nav = docNav.CreateNavigator(); var computer = nav.SelectSingleNode(@"/Event/System/Computer"); var channel = nav.SelectSingleNode(@"/Event/System/Channel"); var eventId = nav.SelectSingleNode(@"/Event/System/EventID"); var level = nav.SelectSingleNode(@"/Event/System/Level"); var timeCreated = nav.SelectSingleNode(@"/Event/System/TimeCreated")?.GetAttribute("SystemTime", ""); var provider = nav.SelectSingleNode(@"/Event/System/Provider")?.GetAttribute("Name", ""); var processId = nav.SelectSingleNode(@"/Event/System/Execution")?.GetAttribute("ProcessID", ""); var threadId = nav.SelectSingleNode(@"/Event/System/Execution")?.GetAttribute("ThreadID", ""); var userId = nav.SelectSingleNode(@"/Event/System/Security")?.GetAttribute("UserID", ""); TimeCreated = DateTimeOffset.Parse(timeCreated, null, DateTimeStyles.AssumeUniversal).ToUniversalTime(); if (eventId != null) { EventId = eventId.ValueAsInt; } if (level != null) { Level = level.ValueAsInt; } if (processId != null) { ProcessId = int.Parse(processId); } if (threadId != null) { ThreadId = int.Parse(threadId); } var payloadNode = nav.SelectSingleNode(@"/Event/EventData"); if (payloadNode == null) { payloadNode = nav.SelectSingleNode(@"/Event/UserData"); } var payloadXml = payloadNode?.OuterXml; if (EventLog.EventLogMaps.ContainsKey(EventId)) { l.Trace($"Found map for event id {EventId}!"); var map = EventLog.EventLogMaps[EventId]; foreach (var mapEntry in map.Maps) { var valProps = new Dictionary <string, string>(); foreach (var me in mapEntry.Values) { //xpath out variables var propVal = nav.SelectSingleNode(me.Value); valProps.Add(me.Name, propVal.Value); } //we have the values, now substitute var propertyValue = mapEntry.PropertyValue; foreach (var valProp in valProps) { propertyValue = propertyValue.Replace($"%{valProp.Key}%", valProp.Value); } //we should now have our new value, so stick it in its place switch (mapEntry.Property.ToUpperInvariant()) { case "USERNAME": UserName = propertyValue; break; case "REMOTEHOST": RemoteHost = propertyValue; break; case "EXECUTABLEINFO": ExecutableInfo = propertyValue; break; case "PAYLOADDATA1": PayloadData1 = propertyValue; break; case "PAYLOADDATA2": PayloadData2 = propertyValue; break; case "PAYLOADDATA3": PayloadData3 = propertyValue; break; case "PAYLOADDATA4": PayloadData4 = propertyValue; break; case "PAYLOADDATA5": PayloadData5 = propertyValue; break; case "PAYLOADDATA6": PayloadData6 = propertyValue; break; default: l.Warn($"Unknown property name '{mapEntry.Property}'! Dropping mapping value of '{propertyValue}'"); break; } } } //sanity checks UserId = userId ?? string.Empty; Provider = provider ?? string.Empty; Channel = channel?.Value ?? string.Empty; Computer = computer?.Value ?? string.Empty; PayloadXml = payloadXml ?? string.Empty; } }