예제 #1
0
        Type GetMessageBodyType(uint realEMsg)
        {
            EMsg eMsg = MsgUtil.GetMsg(realEMsg);

            if (MessageTypeOverrides.BodyMap.ContainsKey(eMsg))
            {
                return(MessageTypeOverrides.BodyMap[eMsg]);
            }

            var protomsgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type =>
            {
                if (type.GetInterfaces().ToList().Find(inter => inter == typeof(IExtensible)) == null)
                {
                    return(false);
                }

                if (type.Name.EndsWith(eMsg.ToString(), StringComparison.OrdinalIgnoreCase))
                {
                    return(true);
                }

                return(false);
            });

            return(protomsgType);
        }
        static object ReadBody(uint rawEMsg, Stream stream, ISteamSerializableHeader header)
        {
            var eMsg    = MsgUtil.GetMsg(rawEMsg);
            var isProto = MsgUtil.IsProtoBuf(rawEMsg);

            var targetJobName = new Lazy <string>(() => ((MsgHdrProtoBuf)header).Proto.target_job_name);

            object body;

            switch (eMsg)
            {
            case EMsg.ServiceMethod:
            case EMsg.ServiceMethodCallFromClient:
                body = UnifiedMessagingHelpers.ReadServiceMethodBody(targetJobName.Value, stream, x => x.GetParameters().First().ParameterType);
                break;

            case EMsg.ServiceMethodResponse:
                body = UnifiedMessagingHelpers.ReadServiceMethodBody(targetJobName.Value, stream, x => x.ReturnType);
                break;

            default:
                body = ReadMessageBody(rawEMsg, stream);
                break;
            }

            return(body);
        }
예제 #3
0
        static IPacketMsg GetPacketMsg(byte[] data)
        {
            uint rawEMsg = BitConverter.ToUInt32(data, 0);
            EMsg eMsg    = MsgUtil.GetMsg(rawEMsg);

            switch (eMsg)
            {
            // certain message types are always MsgHdr
            case EMsg.ChannelEncryptRequest:
            case EMsg.ChannelEncryptResponse:
            case EMsg.ChannelEncryptResult:
                return(new PacketMsg(eMsg, data));
            }

            if (MsgUtil.IsProtoBuf(rawEMsg))
            {
                // if the emsg is flagged, we're a proto message
                return(new PacketClientMsgProtobuf(eMsg, data));
            }
            else
            {
                // otherwise we're a struct message
                return(new PacketClientMsg(eMsg, data));
            }
        }
예제 #4
0
        internal static IPacketMsg GetPacketMsg(byte[] data)
        {
            uint rawEMsg = BitConverter.ToUInt32(data, 0);
            EMsg eMsg    = MsgUtil.GetMsg(rawEMsg);

            switch (eMsg)
            {
            // certain message types are always MsgHdr
            case EMsg.ChannelEncryptRequest:
            case EMsg.ChannelEncryptResponse:
            case EMsg.ChannelEncryptResult:
                return(new PacketMsg(eMsg, data));
            }

            try
            {
                if (MsgUtil.IsProtoBuf(rawEMsg))
                {
                    // if the emsg is flagged, we're a proto message
                    return(new PacketClientMsgProtobuf(eMsg, data));
                }
                else
                {
                    // otherwise we're a struct message
                    return(new PacketClientMsg(eMsg, data));
                }
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("CMClient", "Exception deserializing emsg {0} ({1}).\n{2}", eMsg, MsgUtil.IsProtoBuf(rawEMsg), ex.ToString());
                return(null);
            }
        }
        static TreeNode BuildInfoNode(uint rawEMsg)
        {
            var eMsg = MsgUtil.GetMsg(rawEMsg);

            return(new TreeNode("Info", new[]
            {
                CreateNode("EMsg", string.Format("{0} ({1})", eMsg.ToString(), (long)eMsg)),
                CreateNode("Is ProtoBuf", MsgUtil.IsProtoBuf(rawEMsg).ToString()),
            }));
        }
예제 #6
0
        static TreeNode BuildInfoNode(uint rawEMsg)
        {
            var eMsg     = MsgUtil.GetMsg(rawEMsg);
            var eMsgName = $"EMsg {eMsg:G} ({eMsg:D})";

            if (MsgUtil.IsProtoBuf(rawEMsg))
            {
                return(new TreeNode(eMsgName));
            }

            return(new TreeNode($"{eMsgName} (Non-Protobuf)"));
        }
예제 #7
0
        static TreeNode BuildInfoNode(uint rawEMsg)
        {
            var eMsg = MsgUtil.GetMsg(rawEMsg);

            var eMsgExplorer = new TreeNodeObjectExplorer("EMsg", eMsg);

            return(new TreeNode("Info", new[]
            {
                eMsgExplorer.TreeNode,
                new TreeNodeObjectExplorer("Is Protobuf", MsgUtil.IsProtoBuf(rawEMsg)).TreeNode
            }));
        }
예제 #8
0
        public static Type GetProtobufMessageBodyType(uint realEMsg)
        {
            EMsg eMsg = MsgUtil.GetMsg(realEMsg);

            if (MessageTypeOverrides.BodyMap.ContainsKey(eMsg))
            {
                return(MessageTypeOverrides.BodyMap[eMsg]);
            }

            var protomsgType = SteamKit2Assembly.GetTypes().ToList().Find(t => FilterProtobufMessageBodyType(t, eMsg));

            return(protomsgType);
        }
예제 #9
0
        public static Type GetProtobufMessageBodyType(uint realEMsg)
        {
            EMsg eMsg = MsgUtil.GetMsg(realEMsg);

            if (MessageTypeOverrides.BodyMap.TryGetValue(eMsg, out var wellKnownType))
            {
                return(wellKnownType);
            }

            var protomsgType = SteamKit2Assembly.GetTypes().ToList().Find(t => FilterProtobufMessageBodyType(t, eMsg));

            return(protomsgType);
        }
예제 #10
0
        static object ReadMessageBody(uint rawEMsg, Stream stream)
        {
            var eMsg = MsgUtil.GetMsg(rawEMsg);

            var protoMsgType = MessageTypeFinder.GetProtobufMessageBodyType(rawEMsg);

            if (protoMsgType != null)
            {
                return(RuntimeTypeModel.Default.Deserialize(stream, null, protoMsgType));
            }

            // lets first find the type by checking all EMsgs we have
            var msgType = MessageTypeFinder.GetNonProtobufMessageBodyType(eMsg);

            var eMsgName = eMsg.ToString()
                           .Replace("Econ", "")
                           .Replace("AM", "");

            // check name
            if (msgType == null)
            {
                msgType = MessageTypeFinder.GetSteamKitType(string.Format("SteamKit2.Msg{0}", eMsgName));
            }

            if (msgType != null)
            {
                var body = Activator.CreateInstance(msgType) as ISteamSerializableMessage;
                body.Deserialize(stream);

                return(body);
            }

            msgType = MessageTypeFinder.GetSteamKitType(string.Format("SteamKit2.CMsg{0}", eMsgName));
            if (msgType != null)
            {
                return(Serializer.NonGeneric.Deserialize(msgType, stream));
            }

            // Last resort for protobufs
            if (MsgUtil.IsProtoBuf(rawEMsg))
            {
                var asFieldDictionary = ProtoBufFieldReader.ReadProtobuf(stream);
                return(asFieldDictionary);
            }

            return(null);
        }
예제 #11
0
        static object ReadBody(uint rawEMsg, Stream stream, ISteamSerializableHeader header)
        {
            var eMsg    = MsgUtil.GetMsg(rawEMsg);
            var isProto = MsgUtil.IsProtoBuf(rawEMsg);

            var targetJobName = new Lazy <string>(() => ((MsgHdrProtoBuf)header).Proto.target_job_name);

            object body;

            // Unified Notifications
            if (isProto && eMsg == EMsg.ServiceMethod && !string.IsNullOrEmpty(targetJobName.Value))
            {
                body = ReadServiceMethodBody(targetJobName.Value, stream, x => x.GetParameters().First().ParameterType);
            }
            else
            {
                body = ReadMessageBody(rawEMsg, stream);
            }

            return(body);
        }
예제 #12
0
        internal static IPacketMsg GetPacketMsg(byte[] data)
        {
            if (data.Length < sizeof(uint))
            {
                DebugLog.WriteLine(nameof(CMClient), "PacketMsg too small to contain a message, was only {0} bytes. Message: 0x{1}", data.Length, BitConverter.ToString(data).Replace("-", string.Empty));
                return(null);
            }

            uint rawEMsg = BitConverter.ToUInt32(data, 0);
            EMsg eMsg    = MsgUtil.GetMsg(rawEMsg);

            switch (eMsg)
            {
            // certain message types are always MsgHdr
            case EMsg.ChannelEncryptRequest:
            case EMsg.ChannelEncryptResponse:
            case EMsg.ChannelEncryptResult:
                return(new PacketMsg(eMsg, data));
            }

            try
            {
                if (MsgUtil.IsProtoBuf(rawEMsg))
                {
                    // if the emsg is flagged, we're a proto message
                    return(new PacketClientMsgProtobuf(eMsg, data));
                }
                else
                {
                    // otherwise we're a struct message
                    return(new PacketClientMsg(eMsg, data));
                }
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("CMClient", "Exception deserializing emsg {0} ({1}).\n{2}", eMsg, MsgUtil.IsProtoBuf(rawEMsg), ex.ToString());
                return(null);
            }
        }
        static object ReadBody(uint rawEMsg, Stream stream, ISteamSerializableHeader header)
        {
            var eMsg    = MsgUtil.GetMsg(rawEMsg);
            var isProto = MsgUtil.IsProtoBuf(rawEMsg);

            var targetJobName = new Lazy <string>(() => ((MsgHdrProtoBuf)header).Proto.target_job_name);

            object body;

            switch (eMsg)
            {
            case EMsg.ServiceMethod:
            case EMsg.ServiceMethodSendToClient:
            case EMsg.ServiceMethodCallFromClient:
                body = UnifiedMessagingHelpers.ReadServiceMethodBody(targetJobName.Value, stream, x => x.GetParameters().First().ParameterType);
                break;

            case EMsg.ServiceMethodResponse:
                body = UnifiedMessagingHelpers.ReadServiceMethodBody(targetJobName.Value, stream, x => x.ReturnType);
                break;

            case EMsg.ClientServiceMethodLegacy:
                var tempBody = (CMsgClientServiceMethodLegacy)RuntimeTypeModel.Default.Deserialize(stream, null, typeof(CMsgClientServiceMethodLegacy));
                using (var ms = new MemoryStream(tempBody.serialized_method))
                {
                    body = UnifiedMessagingHelpers.ReadServiceMethodBody(tempBody.method_name, ms, x => x.GetParameters().First().ParameterType);
                }

                break;

            default:
                body = ReadMessageBody(rawEMsg, stream);
                break;
            }

            return(body);
        }
예제 #14
0
        void Dump(PacketItem packet)
        {
            treePacket.Nodes.Clear();

            using (FileStream packetStream = File.OpenRead(packet.FileName))
            {
                uint realEMsg = PeekUInt32(packetStream);
                EMsg eMsg     = MsgUtil.GetMsg(realEMsg);

                var info = new
                {
                    EMsg    = eMsg,
                    IsProto = MsgUtil.IsProtoBuf(realEMsg),
                };
                var    header  = BuildHeader(realEMsg, packetStream);
                var    body    = BuildBody(realEMsg, packetStream);
                object payload = null;
                if (body == null)
                {
                    body    = "Unable to find body message!";
                    payload = "Unable to get payload: Body message missing!";
                }
                else
                {
                    payload = BuildPayload(packetStream);
                }

                TreeNode infoNode    = new TreeNode("Info: ");
                TreeNode headerNode  = new TreeNode("Header: ");
                TreeNode bodyNode    = new TreeNode("Body: ");
                TreeNode gcBodyNode  = new TreeNode("GC Body: ");
                TreeNode payloadNode = new TreeNode("Payload: ");

                DumpType(info, infoNode);
                DumpType(header, headerNode);
                DumpType(body, bodyNode);
                if (body is CMsgGCClient)
                {
                    var gcBody = body as CMsgGCClient;

                    using (var ms = new MemoryStream(gcBody.payload))
                    {
                        var gc = new
                        {
                            emsg   = BuildEMsg(gcBody.msgtype),
                            header = BuildGCHeader(gcBody.msgtype, ms),
                            body   = BuildBody(gcBody.msgtype, ms),
                        };

                        DumpType(gc, gcBodyNode);
                    }
                }
                DumpType(payload, payloadNode);

                treePacket.Nodes.Add(infoNode);
                treePacket.Nodes.Add(headerNode);
                treePacket.Nodes.Add(bodyNode);
                treePacket.Nodes.Add(gcBodyNode);
                treePacket.Nodes.Add(payloadNode);
            }

            treePacket.ExpandAll();
        }
예제 #15
0
        object BuildBody(uint realEMsg, Stream str, uint gcAppid = 0)
        {
            EMsg eMsg = MsgUtil.GetMsg(realEMsg);

            if (eMsg == EMsg.ClientLogonGameServer)
            {
                eMsg = EMsg.ClientLogon; // temp hack for now
            }
            else if (eMsg == EMsg.ClientGamesPlayedWithDataBlob)
            {
                eMsg = EMsg.ClientGamesPlayed;
            }

            var protomsgType = GetMessageBodyType(realEMsg);

            if (protomsgType != null)
            {
                return(RuntimeTypeModel.Default.Deserialize(str, null, protomsgType));
            }

            // lets first find the type by checking all EMsgs we have
            var msgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type =>
            {
                if (type.GetInterfaces().ToList().Find(inter => inter == typeof(ISteamSerializableMessage)) == null)
                {
                    return(false);
                }

                var gcMsg = Activator.CreateInstance(type) as ISteamSerializableMessage;

                return(gcMsg.GetEMsg() == eMsg);
            });

            string eMsgName = eMsg.ToString();

            eMsgName = eMsgName.Replace("Econ", "").Replace("AM", "");

            // check name
            if (msgType == null)
            {
                msgType = GetSteamKitType(string.Format("SteamKit2.Msg{0}", eMsgName));
            }


            if (msgType != null)
            {
                var body = Activator.CreateInstance(msgType) as ISteamSerializableMessage;
                body.Deserialize(str);

                return(body);
            }

            msgType = GetSteamKitType(string.Format("SteamKit2.CMsg{0}", eMsgName));
            if (msgType != null)
            {
                return(Deserialize(msgType, str));
            }

            if (eMsg == EMsg.ClientToGC || eMsg == EMsg.ClientFromGC)
            {
                return(Serializer.Deserialize <CMsgGCClient>(str));
            }

            foreach (var type in GetGCMessageBodyTypeCandidates(realEMsg, gcAppid))
            {
                var streamPos = str.Position;
                try
                {
                    return(Deserialize(type, str));
                }
                catch (Exception)
                {
                    str.Position = streamPos;
                }
            }

            if (!MsgUtil.IsProtoBuf(realEMsg))
            {
                return(null);
            }

            // try reading it as a protobuf
            using (ProtoReader reader = new ProtoReader(str, null, null))
            {
                var fields = new Dictionary <int, List <object> >();

                while (true)
                {
                    int field = reader.ReadFieldHeader();

                    if (field == 0)
                    {
                        break;
                    }

                    object fieldValue = null;

                    switch (reader.WireType)
                    {
                    case WireType.Variant:
                    case WireType.Fixed32:
                    case WireType.Fixed64:
                    case WireType.SignedVariant:
                    {
                        try
                        {
                            fieldValue = reader.ReadInt64();
                        }
                        catch (Exception)
                        {
                            fieldValue = "Unable to read Variant (debugme)";
                        }

                        break;
                    }

                    case WireType.String:
                    {
                        try
                        {
                            fieldValue = reader.ReadString();
                        }
                        catch (Exception)
                        {
                            fieldValue = "Unable to read String (debugme)";
                        }

                        break;
                    }

                    default:
                    {
                        fieldValue = string.Format("{0} is not implemented", reader.WireType);
                        break;
                    }
                    }

                    if (!fields.ContainsKey(field))
                    {
                        fields[field] = new List <object>();
                    }

                    fields[field].Add(fieldValue);
                }

                if (fields.Count > 0)
                {
                    return(fields);
                }
            }

            return(null);
        }
예제 #16
0
        void Dump(PacketItem packet)
        {
            treePacket.Nodes.Clear();

            using (FileStream packetStream = File.OpenRead(packet.FileName))
            {
                uint realEMsg = PeekUInt32(packetStream);
                EMsg eMsg     = MsgUtil.GetMsg(realEMsg);

                var info = new
                {
                    EMsg    = eMsg,
                    IsProto = MsgUtil.IsProtoBuf(realEMsg),
                };
                var    header = BuildHeader(realEMsg, packetStream);
                object body   = null;

                if (MsgUtil.IsProtoBuf(realEMsg) && eMsg == EMsg.ServiceMethod && !string.IsNullOrEmpty(((MsgHdrProtoBuf)header).Proto.target_job_name))
                {
                    body = BuildServiceMethodBody(((MsgHdrProtoBuf)header).Proto.target_job_name, packetStream, x => x.GetParameters().First().ParameterType);
                }
                else if (body == null)
                {
                    body = BuildBody(realEMsg, packetStream);
                }

                object payload = null;
                if (body == null)
                {
                    body    = "Unable to find body message!";
                    payload = "Unable to get payload: Body message missing!";
                }
                else
                {
                    payload = BuildPayload(packetStream);
                }

                TreeNode infoNode          = new TreeNode("Info: ");
                TreeNode headerNode        = new TreeNode("Header: ");
                TreeNode bodyNode          = new TreeNode("Body: ");
                TreeNode gcBodyNode        = new TreeNode("GC Body: ");
                TreeNode payloadNode       = new TreeNode("Payload: ");
                TreeNode serviceMethodNode = new TreeNode("Service Method Body: ");

                DumpType(info, infoNode);
                DumpType(header, headerNode);
                DumpType(body, bodyNode);
                if (body is CMsgGCClient)
                {
                    var gcBody = body as CMsgGCClient;

                    using (var ms = new MemoryStream(gcBody.payload))
                    {
                        var gc = new
                        {
                            emsg   = BuildEMsg(gcBody.msgtype),
                            header = BuildGCHeader(gcBody.msgtype, ms),
                            body   = BuildBody(gcBody.msgtype, ms, gcBody.appid),
                        };

                        DumpType(gc, gcBodyNode);
                    }
                }
                else if (body is CMsgClientServiceMethod)
                {
                    var request = body as CMsgClientServiceMethod;
                    var name    = request.method_name;

                    var serviceBody = BuildServiceMethodBody(request.method_name, request.serialized_method, x => x.GetParameters().First().ParameterType);
                    DumpType(serviceBody, serviceMethodNode);
                }
                else if (body is CMsgClientServiceMethodResponse)
                {
                    var response = body as CMsgClientServiceMethodResponse;
                    var name     = response.method_name;

                    var serviceBody = BuildServiceMethodBody(response.method_name, response.serialized_method_response, x => x.ReturnType);
                    DumpType(serviceBody, serviceMethodNode);
                }

                DumpType(payload, payloadNode);

                treePacket.Nodes.Add(infoNode);
                treePacket.Nodes.Add(headerNode);
                treePacket.Nodes.Add(bodyNode);
                treePacket.Nodes.Add(gcBodyNode);
                treePacket.Nodes.Add(payloadNode);
                treePacket.Nodes.Add(serviceMethodNode);
            }

            treePacket.ExpandAll();
        }
예제 #17
0
        object BuildBody(uint realEMsg, Stream str)
        {
            EMsg eMsg = MsgUtil.GetMsg(realEMsg);

            if (eMsg == EMsg.ClientLogonGameServer)
            {
                eMsg = EMsg.ClientLogon; // temp hack for now
            }
            else if (eMsg == EMsg.ClientGamesPlayedWithDataBlob)
            {
                eMsg = EMsg.ClientGamesPlayed;
            }

            var protomsgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type =>
            {
                if (type.GetInterfaces().ToList().Find(inter => inter == typeof(IExtensible)) == null)
                {
                    return(false);
                }

                if (type.Name.EndsWith(eMsg.ToString()))
                {
                    return(true);
                }

                return(false);
            });

            if (protomsgType != null)
            {
                return(RuntimeTypeModel.Default.Deserialize(str, null, protomsgType));
            }

            // lets first find the type by checking all EMsgs we have
            var msgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type =>
            {
                if (type.GetInterfaces().ToList().Find(inter => inter == typeof(ISteamSerializableMessage)) == null)
                {
                    return(false);
                }

                var gcMsg = Activator.CreateInstance(type) as ISteamSerializableMessage;

                return(gcMsg.GetEMsg() == eMsg);
            });

            string eMsgName = eMsg.ToString();

            eMsgName = eMsgName.Replace("Econ", "").Replace("AM", "");

            // check name
            if (msgType == null)
            {
                msgType = GetSteamKitType(string.Format("SteamKit2.Msg{0}", eMsgName));
            }


            if (msgType != null)
            {
                var body = Activator.CreateInstance(msgType) as ISteamSerializableMessage;
                body.Deserialize(str);

                return(body);
            }

            msgType = GetSteamKitType(string.Format("SteamKit2.CMsg{0}", eMsgName));
            if (msgType != null)
            {
                return(Deserialize(msgType, str));
            }

            if (eMsg == EMsg.ClientToGC || eMsg == EMsg.ClientFromGC)
            {
                return(Serializer.Deserialize <CMsgGCClient>(str));
            }

            var gcMsgName = BuildEMsg(realEMsg);
            var gcMsgPossibleTypePrefixes = new[]
            {
                "SteamKit2.GC.Internal.CMsg",
                "SteamKit2.GC.Dota.Internal.CMsg",
                "SteamKit2.GC.CSGO.Internal.CMsg",
                "SteamKit2.GC.TF.Internal.CMsg",
            };

            var typeMsgName = gcMsgName
                              .Replace("GC", string.Empty)
                              .Replace("k_", string.Empty)
                              .Replace("ESOMsg", string.Empty)
                              .TrimStart('_')
                              .Replace("EMsg", string.Empty);


            if (typeMsgName == "Create" || typeMsgName == "Destroy" || typeMsgName == "Update")
            {
                typeMsgName = "SingleObject";
            }
            else if (typeMsgName == "Multiple")
            {
                typeMsgName = "MultipleObjects";
            }

            var possibleTypes = from type in typeof(CMClient).Assembly.GetTypes()
                                from typePrefix in gcMsgPossibleTypePrefixes
                                where type.GetInterfaces().Contains(typeof(IExtensible))
                                where type.FullName.StartsWith(typePrefix) && type.FullName.EndsWith(typeMsgName)
                                select type;

            foreach (var type in possibleTypes)
            {
                var streamPos = str.Position;
                try
                {
                    return(Deserialize(type, str));
                }
                catch (Exception)
                {
                    str.Position = streamPos;
                }
            }

            if (!MsgUtil.IsProtoBuf(realEMsg))
            {
                return(false);
            }

            // try reading it as a protobuf
            using (ProtoReader reader = new ProtoReader(str, null, null))
            {
                var fields = new Dictionary <int, List <object> >();

                while (true)
                {
                    int field = reader.ReadFieldHeader();

                    if (field == 0)
                    {
                        break;
                    }

                    object fieldValue = null;

                    switch (reader.WireType)
                    {
                    case WireType.Variant:
                    case WireType.Fixed32:
                    case WireType.Fixed64:
                    case WireType.SignedVariant:
                    {
                        try
                        {
                            fieldValue = reader.ReadInt64();
                        }
                        catch (Exception)
                        {
                            fieldValue = "Unable to read Variant (debugme)";
                        }

                        break;
                    }

                    case WireType.String:
                    {
                        try
                        {
                            fieldValue = reader.ReadString();
                        }
                        catch (Exception)
                        {
                            fieldValue = "Unable to read String (debugme)";
                        }

                        break;
                    }

                    default:
                    {
                        fieldValue = string.Format("{0} is not implemented", reader.WireType);
                        break;
                    }
                    }

                    if (!fields.ContainsKey(field))
                    {
                        fields[field] = new List <object>();
                    }

                    fields[field].Add(fieldValue);
                }

                if (fields.Count > 0)
                {
                    return(fields);
                }
            }

            return(null);
        }