Ejemplo n.º 1
0
        public byte[] GetBytes()
        {
            List <byte> data = new List <byte>();

            data.Add((byte)Type);

            data.AddRange(BitConverter.GetBytes(SequenceNumber));

            var epBytes = Encoding.UTF8.GetBytes(EndPoint);

            if (epBytes.Length > byte.MaxValue)
            {
                throw new FormatException("EndPoint string is too long.");
            }

            data.Add((byte)epBytes.Length);
            data.AddRange(epBytes);

            var payload = GetPayload();

            if (payload.Length > ushort.MaxValue)
            {
                throw new FormatException("Payload size is too big");
            }

            data.AddRange(NumberConverter.GetBytes((ushort)payload.Length));
            data.AddRange(payload);

            byte[] bytes = new byte[data.Count + 4];
            data.CopyTo(bytes);
            Crc32Algorithm.ComputeAndWriteToEnd(bytes);

            return(bytes);
        }
Ejemplo n.º 2
0
        public static byte[] PrepareBodyToSend(byte[] someData)

        {
            byte[] someDataWithCrc = new byte[someData.Length + 4];
            someData.CopyTo(someDataWithCrc, 0);
            Crc32Algorithm.ComputeAndWriteToEnd(someDataWithCrc);
            return(someDataWithCrc);
        }
Ejemplo n.º 3
0
        public static byte[] HeaderByteFormat(int messageCode, int length, int packetNum)
        {
            var memoryStream = new MemoryStream();
            var binaryWriter = new BinaryWriter(memoryStream);

            binaryWriter.Write(messageCode);
            binaryWriter.Write(length);
            binaryWriter.Write(packetNum);
            binaryWriter.Write(0); // for crc
            binaryWriter.Close();
            byte[] data = memoryStream.ToArray();

            uint crc = Crc32Algorithm.ComputeAndWriteToEnd(data);

            return(data);
        }
Ejemplo n.º 4
0
        public EventLog(Stream fileStream)
        {
            _stream = fileStream;

            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.ToUInt16(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);

            ErrorRecords = new Dictionary <long, string>();
        }
Ejemplo n.º 5
0
        public ChunkInfo(byte[] chunkBytes, long absoluteOffset, int chunkNumber)
        {
            var l = LogManager.GetLogger("ChunkInfo");

            l.Trace(
                $"\r\n-------------------------------------------- NEW CHUNK at 0x{absoluteOffset:X} ------------------------------------------------\r\n");

            ChunkBytes     = chunkBytes;
            AbsoluteOffset = absoluteOffset;
            ChunkNumber    = chunkNumber;

            ErrorRecords   = new Dictionary <long, string>();
            EventIdMetrics = new Dictionary <long, int>();

            EventRecords = new List <EventRecord>();

            FirstEventRecordNumber     = BitConverter.ToInt64(chunkBytes, 0x8);
            LastEventRecordNumber      = BitConverter.ToInt64(chunkBytes, 0x10);
            FirstEventRecordIdentifier = BitConverter.ToInt64(chunkBytes, 0x18);
            LastEventRecordIdentifier  = BitConverter.ToInt64(chunkBytes, 0x20);

            if (FirstEventRecordIdentifier == -1)
            {
                return;
            }

            var tableOffset = BitConverter.ToUInt32(chunkBytes, 0x28);

            LastRecordOffset = BitConverter.ToUInt32(chunkBytes, 0x2C);
            FreeSpaceOffset  = BitConverter.ToUInt32(chunkBytes, 0x30);

            //TODO how to calculate this? across what data? all event records?
            var crcEventRecordsData = BitConverter.ToUInt32(chunkBytes, 0x34);

            Crc = BitConverter.ToInt32(chunkBytes, 0x7c);

            var inputArray = new byte[120 + 384 + 4];

            Buffer.BlockCopy(chunkBytes, 0, inputArray, 0, 120);
            Buffer.BlockCopy(chunkBytes, 128, inputArray, 120, 384);

            Crc32Algorithm.ComputeAndWriteToEnd(inputArray); // last 4 bytes contains CRC
            CalculatedCrc = BitConverter.ToInt32(inputArray, inputArray.Length - 4);

            var index     = 0;
            var tableData = new byte[0x100];

            Buffer.BlockCopy(chunkBytes, (int)tableOffset, tableData, 0, 0x100);

            StringTableEntries = new Dictionary <uint, StringTableEntry>();

            var stringOffsets = new List <uint>();

            while (index < tableData.Length)
            {
                var stringOffset = BitConverter.ToUInt32(tableData, index);
                index += 4;
                if (stringOffset == 0)
                {
                    continue;
                }

                stringOffsets.Add(stringOffset);
            }

            foreach (var stringOffset in stringOffsets)
            {
                GetStringTableEntry(stringOffset);
            }

            l.Trace("String table entries");
            foreach (var stringTableEntry in StringTableEntries.Keys.OrderBy(t => t))
            {
                l.Trace(StringTableEntries[stringTableEntry]);
            }

            l.Trace("");

            var templateTableData = new byte[0x80];

            Buffer.BlockCopy(chunkBytes, 0x180, templateTableData, 0, 0x80);

            var tableTemplateOffsets = new List <uint>();

            index = 0;
            while (index < templateTableData.Length)
            {
                var templateOffset = BitConverter.ToUInt32(templateTableData, index);
                index += 4;
                if (templateOffset == 0)
                {
                    continue;
                }

                //the actual table definitions live at this Offset + 0x1000 for header, - 10 bytes for some reason.
                //This is where the 0xc op code will be
                tableTemplateOffsets.Add(templateOffset);
            }

            Templates = new Dictionary <int, Template>();

            //to get all the templates and cache them
            foreach (var tableTemplateOffset in tableTemplateOffsets.OrderBy(t => t))
            {
                var actualOffset = absoluteOffset + tableTemplateOffset - 10; //yea, -10
                index = (int)tableTemplateOffset - 10;

                l.Trace(
                    $"Chunk absoluteOffset: 0x{AbsoluteOffset:X} tableTemplateOffset: 0x{tableTemplateOffset:X} actualOffset: 0x {actualOffset:X} chunkBytes[index]: 0x{chunkBytes[index]:X} LastRecordOffset 0x{LastRecordOffset:X} FreeSpaceOffset 0x{FreeSpaceOffset:X}");

                var template = GetTemplate(index);

                if (template == null)
                {
                    l.Trace(
                        $"Implausable template at actual offset: 0x{actualOffset} tableTemplateOffset 0x{tableTemplateOffset:X} FreeSpaceOffset: 0x{FreeSpaceOffset} chunk absolute offset: 0x{AbsoluteOffset:X}");
                    continue;
                }

                if (Templates.ContainsKey(template.TemplateOffset) == false)
                {
                    Templates.Add(template.TemplateOffset - 0x18, template);
                }

                if (template.NextTemplateOffset <= 0)
                {
                    continue;
                }

                var nextTemplateId = template.NextTemplateOffset;

                while (nextTemplateId > 0)
                {
                    var bbb = GetTemplate(nextTemplateId - 10);

                    nextTemplateId = bbb.NextTemplateOffset;

                    if (Templates.ContainsKey(bbb.TemplateOffset) == false)
                    {
                        Templates.Add(bbb.TemplateOffset - 0x18, bbb);
                    }
                }
            }

            l.Trace("Template definitions");
            foreach (var esTemplate in Templates.OrderBy(t => t.Key))
            {
                l.Trace($"key: 0x{esTemplate.Key:X4} {esTemplate.Value}");
            }

            l.Trace("");

            index = (int)tableOffset + 0x100 + 0x80;  //get to start of event Records

            l.Debug($"\r\nChunk data before processing records: {this}");

            const int recordSig = 0x2a2a;

            while (index < chunkBytes.Length)
            {
                var sig = BitConverter.ToInt32(chunkBytes, index);

                if (sig != recordSig)
                {
                    l.Trace(
                        $"Found an invalid signature at 0x{absoluteOffset + index:X}");
                    break;
                }

                var recordOffset = index;

                //do not read past the last known defined record
                if (recordOffset - absoluteOffset > LastRecordOffset)
                {
                    l.Trace(
                        "Reached last record offset. Stopping");
                    break;
                }

                var recordSize = BitConverter.ToUInt32(chunkBytes, index + 4);

                var recordNumber = BitConverter.ToInt64(chunkBytes, index + 8);



                try
                {
                    if (recordNumber < FirstEventRecordIdentifier || recordNumber > LastEventRecordIdentifier)
                    {
                        //outside known good range, so ignore
                        l.Debug(
                            $"Record at offset 0x{AbsoluteOffset + recordOffset:X} falls outside valid record identifier range. Skipping");
                        break;
                    }

                    var ms = new MemoryStream(chunkBytes, index, (int)recordSize);
                    var br = new BinaryReader(ms, Encoding.UTF8);

                    index += (int)recordSize;

                    var er = new EventRecord(br, recordOffset, this);

                    l.Debug(er);

                    EventRecords.Add(er);

                    if (EventIdMetrics.ContainsKey(er.EventId) == false)
                    {
                        EventIdMetrics.Add(er.EventId, 0);
                    }

                    EventIdMetrics[er.EventId] += 1;
                }
                catch (Exception e)
                {
                    l.Trace(
                        $"First event record ident-num: {FirstEventRecordIdentifier}-{FirstEventRecordNumber} Last event record ident-num: {LastEventRecordIdentifier}-{LastEventRecordNumber} last record offset 0x{LastRecordOffset:X}");
                    l.Error(
                        $"Record error at offset 0x{AbsoluteOffset + recordOffset:X}, record #: {recordNumber} error: {e.Message}");

                    if (ErrorRecords.ContainsKey(recordNumber) == false)
                    {
                        ErrorRecords.Add(recordNumber, e.Message);
                    }
                }
            }
        }
Ejemplo n.º 6
0
        private void start()
        {
            int numBytesRead = 0;
            int msgOffset    = 0;

            while (_isProcessing)
            {
                var n = ReadFromStream(prelude);
                numBytesRead += n;
                n             = ReadFromStream(preludeCRC);
                var preludeCRCBytes = preludeCRC.ToArray();
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(preludeCRCBytes);
                }
                numBytesRead += n;
                var inputArray = new byte[prelude.Length + 4];
                System.Buffer.BlockCopy(prelude, 0, inputArray, 0, prelude.Length);

                // write real data to inputArray
                Crc32Algorithm.ComputeAndWriteToEnd(inputArray); // last 4 bytes contains CRC
                // transferring data or writing reading, and checking as final operation
                if (!Crc32Algorithm.IsValidWithCrcAtEnd(inputArray))
                {
                    throw new ArgumentException("invalid prelude CRC");
                }

                if (!Enumerable.SequenceEqual(inputArray.Skip(prelude.Length).Take(4), preludeCRCBytes))
                {
                    throw new ArgumentException("Prelude CRC Mismatch");
                }
                var bytes = prelude.Take(4).ToArray();
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(bytes);
                }
                int totalLength = BitConverter.ToInt32(bytes, 0);
                bytes = prelude.Skip(4).Take(4).ToArray();
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(bytes);
                }

                int headerLength  = BitConverter.ToInt32(bytes, 0);
                int payloadLength = totalLength - headerLength - 16;

                var headers = new byte[headerLength];
                var payload = new byte[payloadLength];
                int num     = ReadFromStream(headers);
                if (num != headerLength)
                {
                    throw new IOException("insufficient data");
                }
                num = ReadFromStream(payload);
                if (num != payloadLength)
                {
                    throw new IOException("insufficient data");
                }

                numBytesRead += num;
                num           = ReadFromStream(messageCRC);
                var messageCRCBytes = messageCRC.ToArray();
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(messageCRCBytes);
                }
                // now verify message CRC
                inputArray = new byte[totalLength];
                System.Buffer.BlockCopy(prelude, 0, inputArray, 0, prelude.Length);
                System.Buffer.BlockCopy(preludeCRC, 0, inputArray, prelude.Length, preludeCRC.Length);
                System.Buffer.BlockCopy(headers, 0, inputArray, prelude.Length + preludeCRC.Length, headerLength);
                System.Buffer.BlockCopy(payload, 0, inputArray, prelude.Length + preludeCRC.Length + headerLength, payloadLength);

                // write real data to inputArray
                Crc32Algorithm.ComputeAndWriteToEnd(inputArray); // last 4 bytes contains CRC
                // transferring data or writing reading, and checking as final operation
                if (!Crc32Algorithm.IsValidWithCrcAtEnd(inputArray))
                {
                    throw new ArgumentException("invalid message CRC");
                }

                if (!Enumerable.SequenceEqual(inputArray.Skip(totalLength - 4).Take(4), messageCRCBytes))
                {
                    throw new ArgumentException("message CRC Mismatch");
                }
                Dictionary <String, String> headerMap = extractHeaders(headers);

                string value = null;
                if (headerMap.TryGetValue(":message-type", out value))
                {
                    if (value.Equals(":error"))
                    {
                        string errorCode    = null;
                        string errorMessage = null;
                        headerMap.TryGetValue(":error-code", out errorCode);
                        headerMap.TryGetValue(":error-message", out errorMessage);
                        throw new SelectObjectContentException(errorCode + ":" + errorMessage);
                    }
                }
                if (headerMap.TryGetValue(":event-type", out value))
                {
                    if (value.Equals("End"))
                    {
                        // throw new UnexpectedShortReadException("Insufficient data");
                        this._isProcessing = false;
                        break;
                    }
                    if (value.Equals("Cont") || payloadLength < 1)
                    {
                        continue;
                    }
                    if (value.Equals("Progress"))
                    {
                        ProgressMessage progress = new ProgressMessage();
                        using (var stream = new MemoryStream(payload))
                            progress = (ProgressMessage) new XmlSerializer(typeof(ProgressMessage)).Deserialize(stream);
                        this.Progress = progress;
                    }
                    if (value.Equals("Stats"))
                    {
                        Console.WriteLine("payload|" + Encoding.UTF7.GetString(payload));
                        StatsMessage stats = new StatsMessage();
                        using (var stream = new MemoryStream(payload))
                            stats = (StatsMessage) new XmlSerializer(typeof(StatsMessage)).Deserialize(stream);
                        this.Stats = stats;
                    }
                    if (value.Equals("Records"))
                    {
                        this.Payload.Write(payload, 0, payloadLength);
                        continue;
                    }
                }
            }
            this._isProcessing = false;
            this.Payload.Seek(0, SeekOrigin.Begin);
            this.payloadStream.Close();
        }
Ejemplo n.º 7
0
        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);
                }
            }
        }
Ejemplo n.º 8
0
        public ChunkInfo(byte[] chunkBytes, long absoluteOffset, int chunkNumber)
        {
            var l = LogManager.GetLogger("ChunkInfo");

            l.Trace(
                $"\r\n-------------------------------------------- NEW CHUNK at 0x{absoluteOffset:X} ------------------------------------------------\r\n");

            ChunkBytes     = chunkBytes;
            AbsoluteOffset = absoluteOffset;
            ChunkNumber    = chunkNumber;

            ErrorRecords = new Dictionary <long, string>();

            EventRecords = new List <EventRecord>();

            FirstEventRecordNumber     = BitConverter.ToInt64(chunkBytes, 0x8);
            LastEventRecordNumber      = BitConverter.ToInt64(chunkBytes, 0x10);
            FirstEventRecordIdentifier = BitConverter.ToInt64(chunkBytes, 0x18);
            LastEventRecordIdentifier  = BitConverter.ToInt64(chunkBytes, 0x20);

            if (FirstEventRecordIdentifier == -1)
            {
                return;
            }

            var tableOffset = BitConverter.ToUInt32(chunkBytes, 0x28);

            LastRecordOffset = BitConverter.ToUInt32(chunkBytes, 0x2C);
            FreeSpaceOffset  = BitConverter.ToUInt32(chunkBytes, 0x30);

            //TODO how to calculate this? across what data? all event records?
            var crcEventRecordsData = BitConverter.ToUInt32(chunkBytes, 0x34);

            Crc = BitConverter.ToInt32(chunkBytes, 0x7c);

            var inputArray = new byte[120 + 384 + 4];

            Buffer.BlockCopy(chunkBytes, 0, inputArray, 0, 120);
            Buffer.BlockCopy(chunkBytes, 128, inputArray, 120, 384);

            Crc32Algorithm.ComputeAndWriteToEnd(inputArray); // last 4 bytes contains CRC
            CalculatedCrc = BitConverter.ToInt32(inputArray, inputArray.Length - 4);

            var index     = 0;
            var tableData = new byte[0x100];

            Buffer.BlockCopy(chunkBytes, (int)tableOffset, tableData, 0, 0x100);

            StringTableEntries = new Dictionary <uint, StringTableEntry>();

            var stringOffsets = new List <uint>();

            var ticksForTimeDelta = 10000000 * EventLog.TimeDiscrepancyThreshold; //10000000 == ticks in a second

            while (index < tableData.Length)
            {
                var stringOffset = BitConverter.ToUInt32(tableData, index);
                index += 4;
                if (stringOffset == 0)
                {
                    continue;
                }

                stringOffsets.Add(stringOffset);
            }

            foreach (var stringOffset in stringOffsets)
            {
                GetStringTableEntry(stringOffset);
            }

            l.Trace("String table entries");
            foreach (var stringTableEntry in StringTableEntries.Keys.OrderBy(t => t))
            {
                l.Trace(StringTableEntries[stringTableEntry]);
            }

            l.Trace("");

            var templateTableData = new byte[0x80];

            Buffer.BlockCopy(chunkBytes, 0x180, templateTableData, 0, 0x80);

            var tableTemplateOffsets = new List <uint>();

            index = 0;
            while (index < templateTableData.Length)
            {
                var templateOffset = BitConverter.ToUInt32(templateTableData, index);
                index += 4;
                if (templateOffset == 0)
                {
                    continue;
                }

                //the actual table definitions live at this Offset + 0x1000 for header, - 10 bytes for some reason.
                //This is where the 0xc op code will be
                tableTemplateOffsets.Add(templateOffset);
            }

            Templates = new Dictionary <int, Template>();

            //to get all the templates and cache them
            foreach (var tableTemplateOffset in tableTemplateOffsets.OrderBy(t => t))
            {
                var actualOffset = absoluteOffset + tableTemplateOffset - 10; //yea, -10
                index = (int)tableTemplateOffset - 10;

                l.Trace(
                    $"Chunk absoluteOffset: 0x{AbsoluteOffset:X} tableTemplateOffset: 0x{tableTemplateOffset:X} actualOffset: 0x {actualOffset:X} chunkBytes[index]: 0x{chunkBytes[index]:X} LastRecordOffset 0x{LastRecordOffset:X} FreeSpaceOffset 0x{FreeSpaceOffset:X}");

                var template = GetTemplate(index);

                if (template == null)
                {
                    l.Trace(
                        $"Implausable template at actual offset: 0x{actualOffset} tableTemplateOffset 0x{tableTemplateOffset:X} FreeSpaceOffset: 0x{FreeSpaceOffset} chunk absolute offset: 0x{AbsoluteOffset:X}");
                    continue;
                }

                if (Templates.ContainsKey(template.TemplateOffset) == false)
                {
                    Templates.Add(template.TemplateOffset - 0x18, template);
                }

                if (template.NextTemplateOffset <= 0)
                {
                    continue;
                }

                var nextTemplateId = template.NextTemplateOffset;

                while (nextTemplateId > 0)
                {
                    var bbb = GetTemplate(nextTemplateId - 10);

                    nextTemplateId = bbb.NextTemplateOffset;

                    if (Templates.ContainsKey(bbb.TemplateOffset) == false)
                    {
                        Templates.Add(bbb.TemplateOffset - 0x18, bbb);
                    }
                }
            }

            l.Trace("Template definitions");
            foreach (var esTemplate in Templates.OrderBy(t => t.Key))
            {
                l.Trace($"key: 0x{esTemplate.Key:X4} {esTemplate.Value}");
            }

            l.Trace("");

            index = (int)tableOffset + 0x100 + 0x80;  //get to start of event Records

            l.Trace($"\r\nChunk data before processing records: {this}");

            const int recordSig = 0x2a2a;

            long lastRecordNumber = 0;

            while (index < chunkBytes.Length)
            {
                var sig = BitConverter.ToInt32(chunkBytes, index);

                if (sig != recordSig)
                {
                    l.Trace(
                        $"Found an invalid signature at 0x{absoluteOffset + index:X}");
                    break;
                }

                var recordOffset = index;

                //do not read past the last known defined record
                if (recordOffset - absoluteOffset > LastRecordOffset)
                {
                    l.Trace(
                        "Reached last record offset. Stopping");
                    break;
                }

                var recordSize = BitConverter.ToUInt32(chunkBytes, index + 4);

                var recordNumber = BitConverter.ToInt64(chunkBytes, index + 8);

                try
                {
                    if (recordNumber < FirstEventRecordIdentifier || recordNumber > LastEventRecordIdentifier)
                    {
                        //outside known good range, so ignore
                        l.Trace(
                            $"Record at offset 0x{AbsoluteOffset + recordOffset:X} falls outside valid record identifier range. Skipping");
                        break;
                    }

                    var ms = new MemoryStream(chunkBytes, index, (int)recordSize);
                    var br = new BinaryReader(ms, Encoding.UTF8);

                    index += (int)recordSize;

                    var er = new EventRecord(br, recordOffset, this);

                    EventRecords.Add(er);

                    lastRecordNumber = er.RecordNumber;

                    if (er.ExtraDataOffset > 0)
                    {
                        try
                        {
                            //hidden data!
                            recordSize = BitConverter.ToUInt32(ms.ToArray(), (int)er.ExtraDataOffset + 4);

                            recordNumber = BitConverter.ToInt64(ms.ToArray(), (int)er.ExtraDataOffset + 8);

                            if (recordNumber != lastRecordNumber)
                            {
                                ms = new MemoryStream(ms.ToArray(), (int)er.ExtraDataOffset, (int)recordSize);
                                br = new BinaryReader(ms, Encoding.UTF8);

                                er = new EventRecord(br, (int)(recordOffset + er.ExtraDataOffset), this);
                                er.HiddenRecord = true;

                                l.Warn($"Record #: {er.RecordNumber} (timestamp: {er.TimeCreated:yyyy-MM-dd HH:mm:ss.fffffff}): Warning! A hidden record was found! Possible DanderSpritz use detected!");

                                EventRecords.Add(er);
                            }
                        }
                        catch (Exception e)
                        {
                            //oh well, we tried
                            //l.Warn($"Error when attemping to recover possible hidden record: {e.Message}");
                        }
                    }



                    //ticksForTimeDelta == totalticks for discrepancy value
                    if (EventLog.LastSeenTicks > 0 && EventLog.LastSeenTicks - ticksForTimeDelta > er.TimeCreated.Ticks)
                    {
                        l.Warn($"Record #: {er.RecordNumber} (timestamp: {er.TimeCreated:yyyy-MM-dd HH:mm:ss.fffffff}): Warning! Time just went backwards! Last seen time before change: {new DateTimeOffset(EventLog.LastSeenTicks,TimeSpan.Zero).ToUniversalTime():yyyy-MM-dd HH:mm:ss.fffffff}");
                    }

                    EventLog.LastSeenTicks = er.TimeCreated.Ticks;
                }
                catch (Exception e)
                {
                    l.Trace(
                        $"First event record ident-num: {FirstEventRecordIdentifier}-{FirstEventRecordNumber} Last event record ident-num: {LastEventRecordIdentifier}-{LastEventRecordNumber} last record offset 0x{LastRecordOffset:X}");
                    l.Error(
                        $"Record error at offset 0x{AbsoluteOffset + recordOffset:X}, record #: {recordNumber} error: {e.Message}");

                    if (ErrorRecords.ContainsKey(recordNumber) == false)
                    {
                        ErrorRecords.Add(recordNumber, e.Message);
                    }
                }
            }
        }