From bffe5192c404974fe8f4e1fcabc39aafa43ff261 Mon Sep 17 00:00:00 2001 From: Ryan Stecker Date: Sun, 9 Sep 2012 20:34:10 -0500 Subject: [PATCH] Implement analyzing GC bodies. --- .../NetHookAnalyzer/SessionForm.cs | 98 +++++++++++++++---- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/Resources/NetHookAnalyzer/NetHookAnalyzer/SessionForm.cs b/Resources/NetHookAnalyzer/NetHookAnalyzer/SessionForm.cs index ba0b85df..26b99868 100644 --- a/Resources/NetHookAnalyzer/NetHookAnalyzer/SessionForm.cs +++ b/Resources/NetHookAnalyzer/NetHookAnalyzer/SessionForm.cs @@ -13,6 +13,7 @@ using System.Reflection; using System.Collections; using SteamKit2.Internal; using ProtoBuf.Meta; +using SteamKit2.GC; namespace NetHookAnalyzer { @@ -62,18 +63,6 @@ namespace NetHookAnalyzer viewPacket.Sort(); } - const uint ProtoMask = 0x80000000; - const uint EMsgMask = ~ProtoMask; - - static EMsg GetMsg( uint integer ) - { - return ( EMsg )( integer & EMsgMask ); - } - static bool IsProtoBuf( uint integer ) - { - return ( integer & ProtoMask ) > 0; - } - void Dump( PacketItem packet ) { treePacket.Nodes.Clear(); @@ -81,12 +70,12 @@ namespace NetHookAnalyzer using ( FileStream packetStream = File.OpenRead( packet.FileName ) ) { uint realEMsg = PeekUInt32( packetStream ); - EMsg eMsg = GetMsg( realEMsg ); + EMsg eMsg = MsgUtil.GetMsg( realEMsg ); var info = new { EMsg = eMsg, - IsProto = IsProtoBuf( realEMsg ), + IsProto = MsgUtil.IsProtoBuf( realEMsg ), }; var header = BuildHeader( realEMsg, packetStream ); var body = BuildBody( realEMsg, packetStream ); @@ -104,22 +93,63 @@ namespace NetHookAnalyzer 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(); } + string BuildEMsg( uint eMsg ) + { + eMsg = MsgUtil.GetGCMsg( eMsg ); + + List fields = new List(); + + fields.AddRange( typeof( SteamKit2.GC.TF2.EGCMsg ).GetFields( BindingFlags.Public | BindingFlags.Static ) ); + fields.AddRange( typeof( SteamKit2.GC.Dota.EGCMsg ).GetFields( BindingFlags.Public | BindingFlags.Static ) ); + fields.AddRange( typeof( SteamKit2.GC.CSGO.EGCMsg ).GetFields( BindingFlags.Public | BindingFlags.Static ) ); + fields.AddRange( typeof( SteamKit2.GC.EGCMsgBase ).GetFields( BindingFlags.Public | BindingFlags.Static ) ); + + var field = fields.SingleOrDefault( f => + { + uint value = ( uint )f.GetValue( null ); + return value == eMsg; + } ); + + if ( field != null ) + return string.Format( "{0} ({1})", field.Name, field.DeclaringType.FullName ); + + return eMsg.ToString(); + } + void DumpType( object obj, TreeNode node ) { @@ -253,7 +283,7 @@ namespace NetHookAnalyzer { ISteamSerializableHeader hdr = null; - if ( IsProtoBuf( realEMsg ) ) + if ( MsgUtil.IsProtoBuf( realEMsg ) ) { hdr = new MsgHdrProtoBuf(); } @@ -265,9 +295,26 @@ namespace NetHookAnalyzer 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; + } + object BuildBody( uint realEMsg, Stream str ) { - EMsg eMsg = GetMsg( realEMsg ); + EMsg eMsg = MsgUtil.GetMsg( realEMsg ); if ( eMsg == EMsg.ClientLogonGameServer ) eMsg = EMsg.ClientLogon; // temp hack for now @@ -324,10 +371,15 @@ namespace NetHookAnalyzer return Deserialize( msgType, str ); } + if ( eMsg == EMsg.ClientToGC || eMsg == EMsg.ClientFromGC ) + { + return Serializer.Deserialize( str ); + } + // try reading it as a protobuf using (ProtoReader reader = new ProtoReader(str, null, null)) { - Dictionary fields = new Dictionary(); + var fields = new Dictionary>(); while(true) { @@ -341,6 +393,9 @@ namespace NetHookAnalyzer switch (reader.WireType) { case WireType.Variant: + case WireType.Fixed32: + case WireType.Fixed64: + case WireType.SignedVariant: { try { @@ -368,12 +423,17 @@ namespace NetHookAnalyzer } default: { - fieldValue = "Not implemented"; + fieldValue = string.Format( "{0} is not implemented", reader.WireType ); break; } } - fields.Add(field, fieldValue); + if ( !fields.ContainsKey( field ) ) + { + fields[ field ] = new List(); + } + + fields[ field ].Add( fieldValue ); } if (fields.Count > 0)