Beispiel #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PacketAnalyzer"/> class.
 /// The configuration is automatically loaded from the configuration files.
 /// </summary>
 public PacketAnalyzer()
 {
     this.LoadAndWatchConfiguration(def => this.serverPacketDefinitions = def, ServerToClientPacketsFile);
     this.LoadAndWatchConfiguration(def => this.clientPacketDefinitions = def, ClientToServerPacketsFile);
 }
Beispiel #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PacketAnalyzer"/> class
 /// with the specified configurations.
 /// </summary>
 /// <param name="clientPacketDefinitions">The client packet definitions.</param>
 /// <param name="serverPacketDefinitions">The server packet definitions.</param>
 public PacketAnalyzer(PacketDefinitions clientPacketDefinitions, PacketDefinitions serverPacketDefinitions)
 {
     this.clientPacketDefinitions = clientPacketDefinitions;
     this.serverPacketDefinitions = serverPacketDefinitions;
 }
Beispiel #3
0
        /// <summary>
        /// Extracts the field value from this packet.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="field">The field definition.</param>
        /// <param name="packet">The packet.</param>
        /// <param name="definitions">The definitions.</param>
        /// <returns>
        /// The value of the field.
        /// </returns>
        private string ExtractFieldValue(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var fieldSize = field.GetFieldSizeInBytes();

            if (field.Type == FieldType.String && field.Index < data.Length)
            {
                return(data.ExtractString(field.Index, fieldSize ?? int.MaxValue, Encoding.UTF8));
            }

            if (field.Type == FieldType.Binary && field.Index < data.Length)
            {
                return(fieldSize.HasValue
                    ? data.Slice(field.Index, fieldSize.Value).AsString()
                    : data.Slice(field.Index).AsString());
            }

            if (data.Length < field.Index + fieldSize)
            {
                return(string.Empty);
            }

            return(field.Type switch
            {
                FieldType.Byte => data.Slice(field.Index)
                .GetByteValue(field.LengthSpecified ? field.Length : 8, field.LeftShifted)
                .ToString(),
                FieldType.Boolean => data.Slice(field.Index).GetBoolean(field.LeftShifted).ToString(),
                FieldType.IntegerLittleEndian => ReadUInt32LittleEndian(data.Slice(field.Index)).ToString(),
                FieldType.IntegerBigEndian => ReadUInt32BigEndian(data.Slice(field.Index)).ToString(),
                FieldType.ShortLittleEndian => ReadUInt16LittleEndian(data.Slice(field.Index)).ToString(),
                FieldType.ShortBigEndian => ReadUInt16BigEndian(data.Slice(field.Index)).ToString(),
                FieldType.LongLittleEndian => ReadUInt64LittleEndian(data.Slice(field.Index)).ToString(),
                FieldType.LongBigEndian => ReadUInt64BigEndian(data.Slice(field.Index)).ToString(),
                FieldType.Enum => this.ExtractEnumValue(data, field, packet, definitions),
                FieldType.StructureArray => this.ExtractStructureArrayValues(data, field, packet, definitions),
                FieldType.Float => BitConverter.ToSingle(data.Slice(field.Index)).ToString(CultureInfo.InvariantCulture),
                _ => string.Empty
            });
Beispiel #4
0
 /// <summary>
 /// Extracts the field value from this packet or returns an error message, if it couldn't be extracted.
 /// </summary>
 /// <param name="data">The data.</param>
 /// <param name="field">The field definition.</param>
 /// <param name="packet">The packet.</param>
 /// <param name="definitions">The definitions.</param>
 /// <returns>
 /// The value of the field or the error message.
 /// </returns>
 private string ExtractFieldValueOrGetError(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
 {
     try
     {
         return(this.ExtractFieldValue(data, field, packet, definitions));
     }
     catch (Exception e)
     {
         return($"{e.GetType().Name}: {e.Message}");
     }
 }
Beispiel #5
0
        private string ExtractEnumValue(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var byteValue      = data.Slice(field.Index).GetByteValue(field.LengthSpecified ? field.Length : 8, field.LeftShifted);
            var enumDefinition = packet.Enums?.FirstOrDefault(e => e.Name == field.TypeName)
                                 ?? definitions.Enums?.FirstOrDefault(e => e.Name == field.TypeName)
                                 ?? this.commonDefinitions?.Enums?.FirstOrDefault(e => e.Name == field.TypeName);
            var enumValue = enumDefinition?.Values.FirstOrDefault(v => v.Value == byteValue);

            return($"{data[field.Index]} ({enumValue?.Name ?? "unknown"})");
        }
Beispiel #6
0
        private string ExtractStructureArrayValues(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var type = packet.Structures?.FirstOrDefault(s => s.Name == field.TypeName)
                       ?? definitions.Structures?.FirstOrDefault(s => s.Name == field.TypeName)
                       ?? this.commonDefinitions.Structures?.FirstOrDefault(s => s.Name == field.TypeName);

            if (type == null)
            {
                return(data.Slice(field.Index).AsString());
            }

            var countField = packet.Fields.FirstOrDefault(f => f.Name == field.ItemCountField)
                             ?? packet.Structures?.SelectMany(s => s.Fields).FirstOrDefault(f => f.Name == field.ItemCountField);
            int count = int.Parse(this.ExtractFieldValue(data, countField, packet, definitions));

            if (count == 0)
            {
                return(string.Empty);
            }

            var typeLength    = type.Length > 0 ? type.Length : this.DetermineFixedStructLength(data, field, type, count);
            var stringBuilder = new StringBuilder();
            var restData      = data.Slice(field.Index);

            for (int i = 0; i < count; i++)
            {
                var currentLength = typeLength ?? this.DetermineDynamicStructLength(restData, type, packet);
                var elementData   = restData.Slice(0, currentLength);
                restData = restData.Slice(currentLength);

                stringBuilder.Append(Environment.NewLine)
                .Append(field.Name + $"[{i}]:");
                stringBuilder.Append(Environment.NewLine)
                .Append("  Raw: ").Append(elementData.AsString());
                foreach (var structField in type.Fields)
                {
                    stringBuilder.Append(Environment.NewLine)
                    .Append("  ").Append(structField.Name).Append(": ").Append(this.ExtractFieldValue(elementData, structField, packet, definitions));
                }
            }

            return(stringBuilder.ToString());
        }
Beispiel #7
0
        /// <summary>
        /// Extracts the field value from this packet.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="field">The field definition.</param>
        /// <param name="packet">The packet.</param>
        /// <param name="definitions">The definitions.</param>
        /// <returns>
        /// The value of the field.
        /// </returns>
        private string ExtractFieldValue(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var fieldSize = field.GetFieldSizeInBytes();

            if (field.Type == FieldType.String && field.Index < data.Length)
            {
                return(data.ExtractString(field.Index, fieldSize ?? int.MaxValue, Encoding.UTF8));
            }

            if (field.Type == FieldType.Binary && field.Index < data.Length)
            {
                return(fieldSize.HasValue
                    ? data.Slice(field.Index, fieldSize.Value).AsString()
                    : data.Slice(field.Index).AsString());
            }

            if (data.Length < field.Index + fieldSize)
            {
                return(string.Empty);
            }

            switch (field.Type)
            {
            case FieldType.Byte:
                return(data.Slice(field.Index).GetByteValue(field.LengthSpecified ? field.Length : 8, field.LeftShifted).ToString());

            case FieldType.Boolean:
                return(data.Slice(field.Index).GetBoolean(field.LeftShifted).ToString());

            case FieldType.Integer:
                return(data.Slice(field.Index).GetIntegerLittleEndian().ToString());

            case FieldType.IntegerBigEndian:
                return(data.Slice(field.Index).GetIntegerBigEndian().ToString());

            case FieldType.Short:
                return(data.Slice(field.Index).GetShortLittleEndian().ToString());

            case FieldType.ShortBigEndian:
                return(data.Slice(field.Index).GetShortBigEndian().ToString());

            case FieldType.Long:
                return(data.Slice(field.Index).GetLongLittleEndian().ToString());

            case FieldType.LongBigEndian:
                return(data.Slice(field.Index).GetLongBigEndian().ToString());

            case FieldType.Enum:
                return(this.ExtractEnumValue(data, field, packet, definitions));

            case FieldType.StructureArray:
                return(this.ExtractStructureArrayValues(data, field, packet, definitions));

            case FieldType.Float:
                return(BitConverter.ToSingle(data.Slice(field.Index)).ToString(CultureInfo.InvariantCulture));

            default:
                return(string.Empty);
            }
        }