Example #1
0
        static void HandleEntry(PacketLogReader reader, PacketLogEntry entry,
                                Regex[] regexes, PacketStatistics stats,
                                PacketSerializer serializer, StreamWriter result)
        {
            stats.TotalPackets++;

            var name = serializer.Messages.Game.OpCodeToName[entry.OpCode];

            if (regexes.All(r => !r.IsMatch(name)))
            {
                stats.IgnoredPackets++;
                return;
            }

            result.WriteLine("[{0:yyyy-MM-dd HH:mm:ss:fff}] {1} {2}: {3} ({4} bytes)",
                             entry.Timestamp.ToLocalTime(),
                             reader.Servers[entry.ServerId].Name,
                             entry.Direction.ToDirectionString(), name,
                             entry.Payload.Count);

            var parsed  = serializer.Create(entry.OpCode);
            var payload = entry.Payload.ToArray();

            if (payload.Length != 0)
            {
                if ((_hex == HexDumpMode.Unknown && parsed == null) ||
                    _hex == HexDumpMode.All)
                {
                    result.WriteLine();
                    result.WriteLine(new RawPacket(name)
                    {
                        Payload = payload
                    });
                }

                if ((_analysis == AnalysisMode.Unknown && parsed == null) ||
                    _analysis == AnalysisMode.All)
                {
                    var arrays = PacketAnalysis.FindArrays(payload);

                    if (arrays.Any())
                    {
                        result.WriteLine();
                        result.WriteLine("Potential arrays:");
                        result.WriteLine();

                        foreach (var arr in arrays)
                        {
                            stats.PotentialArrays++;

                            result.WriteLine(arr);
                        }
                    }

                    var strings = PacketAnalysis.FindStrings(payload,
                                                             _whiteSpace, _control, _length);

                    if (strings.Any())
                    {
                        result.WriteLine();
                        result.WriteLine("Potential strings:");
                        result.WriteLine();

                        foreach (var str in strings)
                        {
                            stats.PotentialStrings++;

                            result.WriteLine(str);
                        }
                    }
                }
            }

            stats.AddPacket(name, parsed != null, payload.Length);

            if (parsed != null)
            {
                if (_parse)
                {
                    stats.ParsedPackets++;

                    serializer.Deserialize(payload, parsed);

                    for (var i = 0; i < _roundtrips; i++)
                    {
                        var payload2 = serializer.Serialize(parsed);
                        var len      = payload.Length;
                        var len2     = payload2.Length;

                        Assert.Check(len2 == len,
                                     $"Payload lengths for {name} don't match ({len2} versus {len}).");

                        if (i > 0)
                        {
                            Assert.Check(payload2.SequenceEqual(payload),
                                         $"Payloads for {name} don't match after roundtrip.");
                        }

                        if (i != _roundtrips - 1)
                        {
                            serializer.Deserialize(payload2, parsed);
                        }

                        payload = payload2;
                    }

                    result.WriteLine();
                    result.WriteLine(parsed);
                }
            }

            result.WriteLine();
        }
Example #2
0
        public static int Run(string[] args)
        {
            try
            {
                if (!HandleArguments(ref args))
                {
                    return(0);
                }
            }
            catch (OptionException e)
            {
                Console.WriteLine(e.Message);
                return(1);
            }

            if (args.Length != 1)
            {
                Console.WriteLine("Expected exactly one input file argument.");
                return(1);
            }

            Log.Level           = LogLevel.Debug;
            Log.TimestampFormat = "HH:mm:ss:fff";

            var color = Console.ForegroundColor;

            Log.Loggers.Add(new ConsoleLogger(false,
                                              color, color, color, color));

            if (!Debugger.IsAttached)
            {
                AppDomain.CurrentDomain.UnhandledException += UnhandledException;
            }

            var input   = args[0];
            var output  = _output ?? Path.ChangeExtension(input, "txt");
            var regexes = _regexes.Select(x => new Regex(x, RegexOptions))
                          .DefaultIfEmpty(new Regex(".*", RegexOptions))
                          .ToArray();

            _log.Basic("Parsing {0}...", input);

            var reader     = new PacketLogReader(input);
            var serializer = new PacketSerializer(
                new OpCodeTable(true, reader.Region),
                new OpCodeTable(false, reader.Region));
            var stats = new PacketStatistics();

            using (var result = new StreamWriter(new FileStream(output,
                                                                FileMode.Create, FileAccess.Write)))
            {
                foreach (var entry in reader.EnumerateAll())
                {
                    stats.TotalPackets++;

                    var name = serializer.GameMessages.OpCodeToName[entry.OpCode];

                    if (regexes.Any(r => !r.IsMatch(name)))
                    {
                        stats.IgnoredPackets++;

                        continue;
                    }

                    stats.RelevantPackets++;

                    result.WriteLine("[{0:yyyy-MM-dd HH:mm:ss:fff}] {1} {2}: {3} ({4} bytes)",
                                     entry.Timestamp.ToLocalTime(), entry.ServerName,
                                     entry.Direction.ToDirectionString(), name,
                                     entry.Payload.Count);

                    var parsed  = serializer.Create(entry.OpCode);
                    var payload = entry.Payload.ToArray();

                    if (payload.Length != 0)
                    {
                        if ((_hex == HexDumpMode.Unknown && parsed == null) ||
                            _hex == HexDumpMode.All)
                        {
                            result.WriteLine();
                            result.WriteLine(new RawPacket(name)
                            {
                                Payload = payload
                            });
                        }

                        if ((_analysis == AnalysisMode.Unknown && parsed == null) ||
                            _analysis == AnalysisMode.All)
                        {
                            var arrays = PacketAnalysis.FindArrays(payload);

                            if (arrays.Any())
                            {
                                result.WriteLine();
                                result.WriteLine("Potential arrays:");
                                result.WriteLine();

                                foreach (var arr in arrays)
                                {
                                    stats.PotentialArrays++;

                                    result.WriteLine(arr);
                                }
                            }

                            var strings = PacketAnalysis.FindStrings(payload,
                                                                     _whiteSpace, _control, _length);

                            if (strings.Any())
                            {
                                result.WriteLine();
                                result.WriteLine("Potential strings:");
                                result.WriteLine();

                                foreach (var str in strings)
                                {
                                    stats.PotentialStrings++;

                                    result.WriteLine(str);
                                }
                            }
                        }
                    }
                    else
                    {
                        stats.EmptyPackets++;
                    }

                    if (parsed != null)
                    {
                        stats.KnownPackets++;

                        if (_parse)
                        {
                            stats.ParsedPackets++;

                            for (var i = 0; i < _roundtrips + 1; i++)
                            {
                                serializer.Deserialize(payload, parsed);

                                var payload2 = serializer.Serialize(parsed);

                                Assert.Check(payload2.Length == payload.Length,
                                             "Payload lengths must match after roundtrip.");

                                if (i > 0)
                                {
                                    Assert.Check(payload2.SequenceEqual(payload),
                                                 "Payloads must match after first roundtrip.");
                                }

                                payload = payload2;
                            }

                            result.WriteLine();
                            result.WriteLine(parsed);
                        }
                    }
                    else
                    {
                        stats.UnknownPackets++;
                    }

                    result.WriteLine();
                }
            }

            _log.Basic("Parsed packets to {0}", output);

            if (_stats)
            {
                void PrintValue(string name, int value)
                {
                    _log.Info("{0,17}: {1}", name, value);
                }

                void PrintPacketValue(string name, int value)
                {
                    _log.Info("{0,17}: {1} ({2:P2})", name, value,
                              (double)value / stats.RelevantPackets);
                }

                PrintValue("Total packets", stats.TotalPackets);
                PrintPacketValue("Relevant packets", stats.RelevantPackets);
                PrintPacketValue("Ignored packets", stats.IgnoredPackets);
                PrintPacketValue("Empty packets", stats.EmptyPackets);
                PrintPacketValue("Unknown packets", stats.UnknownPackets);
                PrintPacketValue("Known packets", stats.KnownPackets);
                PrintPacketValue("Parsed packets", stats.ParsedPackets);
                PrintValue("Potential arrays", stats.PotentialArrays);
                PrintValue("Potential strings", stats.PotentialStrings);
            }

            return(0);
        }