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)); } }
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); }
static ISteamSerializableHeader ReadHeader(uint rawEMsg, Stream stream) { ISteamSerializableHeader header; if (MsgUtil.IsProtoBuf(rawEMsg)) { header = new MsgHdrProtoBuf(); } else { switch (rawEMsg) { case (uint)EMsg.ChannelEncryptRequest: case (uint)EMsg.ChannelEncryptResponse: case (uint)EMsg.ChannelEncryptResult: header = new MsgHdr(); break; default: header = new ExtendedClientMsgHdr(); break; } } header.Deserialize(stream); return(header); }
static object ReadMessageBody(uint rawEMsg, Stream stream, uint gcAppId) { foreach (var type in MessageTypeFinder.GetGCMessageBodyTypeCandidates(rawEMsg, gcAppId)) { var streamPos = stream.Position; try { return(RuntimeTypeModel.Default.Deserialize(stream, null, type)); } catch (Exception) { stream.Position = streamPos; } } // Last resort for protobufs if (MsgUtil.IsProtoBuf(rawEMsg)) { try { var asFieldDictionary = ProtoBufFieldReader.ReadProtobuf(stream); return(asFieldDictionary); } catch (ProtoException) { return("Invalid protobuf data."); } catch (EndOfStreamException ex) { return("Error parsing SO data: " + ex.Message); } } return(null); }
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()), })); }
private static IPacketGCMsg GetPacketGCMsg(uint eMsg, byte[] data) { // strip off the protobuf flag uint realEMsg = MsgUtil.GetGCMsg(eMsg); if (MsgUtil.IsProtoBuf(eMsg)) { return(new PacketClientGCMsgProtobuf(realEMsg, data)); } return(new PacketClientGCMsg(realEMsg, data)); }
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 })); }
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)")); }
static IGCSerializableHeader ReadGameCoordinatorHeader(uint rawEMsg, Stream stream) { IGCSerializableHeader header = null; if (MsgUtil.IsProtoBuf(rawEMsg)) { header = new MsgGCHdrProtoBuf(); } else { header = new MsgGCHdr(); } header.Deserialize(stream); return(header); }
static ISteamSerializableHeader ReadHeader(uint rawEMsg, Stream stream) { ISteamSerializableHeader header; if (MsgUtil.IsProtoBuf(rawEMsg)) { header = new MsgHdrProtoBuf(); } else { header = new ExtendedClientMsgHdr(); } header.Deserialize(stream); return(header); }
ISteamSerializableHeader BuildHeader(uint realEMsg, Stream str) { ISteamSerializableHeader hdr = null; if (MsgUtil.IsProtoBuf(realEMsg)) { hdr = new MsgHdrProtoBuf(); } else { hdr = new ExtendedClientMsgHdr(); } hdr.Deserialize(str); return(hdr); }
IGCSerializableHeader BuildGCHeader(uint realEMsg, Stream str) { IGCSerializableHeader hdr = null; if (MsgUtil.IsProtoBuf(realEMsg)) { hdr = new MsgGCHdrProtoBuf(); } else { hdr = new MsgGCHdr(); } hdr.Deserialize(str); return(hdr); }
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); }
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); }
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); }
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(); }
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); }
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); }
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(); }