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

            if (args.Length != 1)
            {
                Console.Error.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, 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 stats = new PacketStatistics();

            using (var reader = new PacketLogReader(input))
            {
                if (_header)
                {
                    _log.Info(string.Empty);
                    _log.Info("Version: {0}", reader.Version);
                    _log.Info("Compressed: {0}", reader.Compressed);
                    _log.Info("Region: {0}", reader.Messages.Region);
                    _log.Info("Servers:");

                    foreach (var srv in reader.Servers.Values)
                    {
                        _log.Info("  {0} ({1}): {2} -> {3}", srv.Name, srv.Id,
                                  srv.RealEndPoint, srv.ProxyEndPoint);
                    }

                    _log.Info(string.Empty);
                }

                PacketSerializer serializer;

                switch (_backend)
                {
                case PacketSerializerBackend.Reflection:
                    serializer = new ReflectionPacketSerializer(
                        reader.Messages);
                    break;

                case PacketSerializerBackend.Compiler:
                    serializer = new CompilerPacketSerializer(
                        reader.Messages);
                    break;

                default:
                    throw Assert.Unreachable();
                }

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

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

            PrintStats(stats);

            return(0);
        }
示例#2
0
        static void PrintStats(PacketStatistics stats)
        {
            if (_stats)
            {
                void PrintValue(string name, int value,
                                string trail = "")
                {
                    _log.Info("{0,17}: {1}{2}", name, value, trail);
                }

                void PrintPercentageValue(string name, int value, int total)
                {
                    PrintValue(name, value, total == 0 ? string.Empty :
                               $" ({(double)value / total:P2})");
                }

                void PrintTotalPacketValue(string name, int value)
                {
                    PrintPercentageValue(name, value, stats.TotalPackets);
                }

                void PrintRelevantPacketValue(string name, int value)
                {
                    PrintPercentageValue(name, value, stats.RelevantPackets);
                }

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

            if (_summary)
            {
                void PrintSummary(KeyValuePair <string,
                                                PacketStatistics.SummaryEntry> kvp)
                {
                    var entry = kvp.Value;
                    var total = stats.RelevantPackets;
                    var sizes = entry.Sizes;

                    _log.Info("  {0}", kvp.Key);
                    _log.Info("    Count: {0}{1}", entry.Count, total != 0 ?
                              $" ({(double)entry.Count / total:P2})" : string.Empty);
                    _log.Info("    Sizes: Min = {0}, Max = {1}, Avg = {2}",
                              sizes.Min(), sizes.Max(), (int)sizes.Average());
                    _log.Info(string.Empty);
                }

                void PrintSummaryList(string header,
                                      Func <PacketStatistics.SummaryEntry, bool> predicate)
                {
                    var packets = stats.Packets.Where(x => predicate(x.Value))
                                  .OrderBy(x => x.Key);

                    if (!packets.Any())
                    {
                        return;
                    }

                    _log.Info(string.Empty);
                    _log.Info($"{header}:");
                    _log.Info(string.Empty);

                    foreach (var kvp in packets)
                    {
                        PrintSummary(kvp);
                    }
                }

                PrintSummaryList("Known packets", x => x.Known);
                PrintSummaryList("Unknown packets", x => !x.Known);
            }
        }
示例#3
0
 static void PrintStatistics(PacketStatistics stats)
 {
     if (_stats)
     {
示例#4
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();
        }
示例#5
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);
        }