// Dumps the current packet onto the tee stream.
        // The packet has to be reconstructed according to the rules found in the respective
        // encoding(..) method.
        private void DumpPacket(string typeName, object thisObj)
        {
            // Object that does the duplication of packets.
            var dumper = DumpServer.Get();

            // the name of the packet is retrievable in generalized form.
            Type packetType = thisObj.GetType();
            // More packet specific details.
            string packetTypeString = packetType.Name;
            int    methodID         = -1;
            int    serviceID        = -1;

            if (packetType.Equals(typeof(BattleNetPacket)))
            {
                var packet = ((BattleNetPacket)thisObj);

                // Debug information
                bnet.protocol.Header header = packet.GetHeader();
                methodID  = (int)header.MethodId;
                serviceID = (int)header.ServiceId;

                byte[] packetData = DumpServer.SerializePacket(packet);
                dumper.SendPacket(PacketType.Battlenetpacket, PacketDirection.Incoming, 0, packetData);
            }
            else if (packetType.Equals(typeof(PegasusPacket)))
            {
                var packet = ((PegasusPacket)thisObj);

                // Debug information
                serviceID = packet.Type;

                byte[] packetData = DumpServer.SerializePacket(packet);
                dumper.SendPacket(PacketType.Pegasuspacket, PacketDirection.Incoming, 0, packetData);
            }
            else
            {
                // Returning false here would just introduce undefined behaviour
                HookRegistry.Panic("Unknown packet type!");
            }

            string message = string.Format(RECEIVED_PACKET_NOTIFY, packetTypeString, serviceID, methodID);

            HookRegistry.Get().Internal_Log(message);
        }
        // Dump data just as we receive it.
        private void DumpPacket(string typeName, object[] args)
        {
            // Object that does the duplication of packets.
            var dumper = DumpServer.Get();

            object packetObj  = args[0];
            Type   packetType = packetObj.GetType();

            string packetTypeString = packetType.Name;
            int    methodID         = -1;
            int    serviceID        = -1;
            object body             = null;

            if (packetType.Equals(typeof(BattleNetPacket)))
            {
                var packet = ((BattleNetPacket)packetObj);

                // Debug information
                bnet.protocol.Header header = packet.GetHeader();
                methodID  = (int)header.MethodId;
                serviceID = (int)header.ServiceId;
                body      = packet.GetBody();

                // Calculate the hash of the body, which is passed to analyzers.
                uint bodyHash = Util.GenerateHashFromObjectType(body);

                byte[] packetData = DumpServer.SerializePacket(packet);
                dumper.SendPacket(PacketType.Battlenetpacket, PacketDirection.Outgoing, bodyHash, packetData);

                // Test for LogonRequest body packet, since that one contains the version string
                var logonRequest = body as LogonRequest;
                if (logonRequest != null)
                {
                    dumper.InitialiseHandshake(logonRequest.Version);
                }
            }
            else if (packetType.Equals(typeof(PegasusPacket)))
            {
                var packet = ((PegasusPacket)packetObj);

                // Debug information
                serviceID = packet.Type;
                body      = packet.GetBody();

                // Calculate the hash of the body, which is passed to analyzers.
                uint bodyHash = Util.GenerateHashFromObjectType(body);

                byte[] packetData = DumpServer.SerializePacket(packet);
                dumper.SendPacket(PacketType.Pegasuspacket, PacketDirection.Outgoing, bodyHash, packetData);
            }
            else
            {
                // Returning false here would just introduce undefined behaviour
                HookRegistry.Panic("Unknown packet type!");
            }

            string message = string.Format(SENT_PACKET_NOTIFY, packetTypeString, serviceID, methodID,
                                           body.GetType().FullName);

            HookRegistry.Get().Internal_Log(message);
        }
Exemple #3
0
        object OnCall(string typeName, string methodName, object thisObj, object[] args, IntPtr[] refArgs, int[] refIdxMatch)
        {
            if (typeName != "System.Net.Sockets.Socket" ||
                (methodName != "EndSend" && methodName != "EndReceive"))
            {
                return(null);
            }

            // Socket is a low-level construct so we must guard ourselves robustly against race conditions.
            if (!ReentrantEnter(thisObj))
            {
                return(null);
            }

            /* Actual hook code */

            bool isOutgoing = methodName.EndsWith("Send");
            int  OPResult   = 0;
            var  dumpServer = DumpServer.Get();
            // True if we need to feedback the error code returned by the proxy method.
            bool feedbackErrorCode = false;

            var thisSocket = thisObj as Socket;

            if (thisSocket == null)
            {
                HookRegistry.Panic("SocketHook - `thisObj` is NOT a Socket object");
            }

            // We expect 1 referenceArgument, which makes the total passed argument equal to 2.
            // The argument in question is `out SocketError`
            if (refArgs != null && refArgs.Length == 1)
            {
                if (args.Length != 2 || refIdxMatch == null || refIdxMatch[0] != 1)
                {
                    string message = String.Format("SocketHook - {0} - Got 1 reference argument, but total arguments don't match: {1} <=> 2",
                                                   thisSocket.GetHashCode(), args.Length);
                    HookRegistry.Panic(message);
                }
                else
                {
                    HookRegistry.Debug("SocketHook - {0} - Valid referenced argument!", thisSocket.GetHashCode());
                    feedbackErrorCode = true;
                }
            }

            dumpServer.PreparePartialBuffers(thisSocket, false);

            // Fetch the asyncModel early to prevent it being cleaned up
            // directly after operation end.
            var asyncResult = args[0] as IAsyncResult;

            if (asyncResult == null)
            {
                HookRegistry.Panic("SocketHook - asyncResult == null");
            }

            if (isOutgoing)
            {
                int sentBytes = (int)ProxyEndWrite(thisObj, ref args);

                // buffer holds the transmitted contents.
                // requestedBytes holds the amount of bytes requested when starting the operation.
                //	=> This amount gets decreased, towards 0, each time bytes are sent.
                //	=> The actual amount of bytes sent are found inside sentBytes.
                // offset is the starting offset, within buffer, of data to be written when starting
                // the operation.
                //	=> This amount gets increased, towards orignal value of size, each time bytes are sent.
                //	=> The actual offset would then be (offset-sentBytes)!

                OPResult = sentBytes;

                //processedBytes = sentBytes;
                // Update offset parameter.
                //offset = offset-sentBytes;
            }
            else
            {
                int readBytes = (int)ProxyEndRead(thisObj, ref args);
                OPResult = readBytes;
                //processedBytes = readBytes;
            }

            // These variables have a different meaning depending on the operation; read or write.
            byte[] buffer = GetAsyncBuffer(asyncResult);
            // Offset in buffer where relevant data starts.
            int offset         = GetAsyncOffset(asyncResult);
            int requestedBytes = GetAsyncRequestedBytes(asyncResult);
            // Amount of bytes actually processed by the operation.
            int processedBytes = OPResult;

            if (buffer != null)
            {
                if (offset + processedBytes > buffer.Length)
                {
                    offset -= processedBytes;
                }

                // HookRegistry.Log("SocketHook - {0} - writing", thisSocket.GetHashCode());
                dumpServer.PartialData(thisSocket, !isOutgoing, buffer, offset, processedBytes, isWrapping: false, singleDecode: false);
            }
            else
            {
                HookRegistry.Log("SocketHook - {0} - buffer == null", thisSocket.GetHashCode());
            }

            if (feedbackErrorCode == true)
            {
                var    errorCode    = (SocketError)args[1];
                IntPtr errorCodePtr = refArgs[0];
                HookRegistry.Debug("SocketHook - {0} - Writing `{1}` to refPtr", thisSocket.GetHashCode(), errorCode.ToString());
                Marshal.StructureToPtr(errorCode, errorCodePtr, true);
            }

            ReentrantLeave(thisObj);
            return(OPResult);
        }
Exemple #4
0
        object OnCall(string typeName, string methodName, object thisObj, object[] args, IntPtr[] refArgs, int[] refIdxMatch)
        {
            if (typeName != "System.Net.Security.SslStream" ||
                (methodName != "EndWrite" && methodName != "EndRead"))
            {
                return(null);
            }

            if (_reentrant == true)
            {
                return(null);
            }

            /* Actual hook code */

            _reentrant = true;

            bool   isWriting  = methodName.EndsWith("Write");
            object OPresult   = null;
            var    dumpServer = DumpServer.Get();
            int    readBytes  = -1;

            Socket underlyingSocket = GetUnderlyingSocket(thisObj);

            dumpServer.PreparePartialBuffers(underlyingSocket, true);

            // Fetch the asyncModel early to prevent it being cleaned up
            // directly after operation end.
            var asyncResult = args[0] as IAsyncResult;

            if (asyncResult == null)
            {
                HookRegistry.Panic("SslStreamHook - asyncResult == null");
            }

            if (isWriting)
            {
                OPresult = ProxyEndWrite(thisObj, args);
                // Buffer holds written data,
                // offset holds offset within buffer where writing started,
                // count holds amount of written bytes.
            }
            else
            {
                readBytes = (int)ProxyEndRead(thisObj, args);
                OPresult  = readBytes;
                // Buffer holds read data,
                // offset holds offset within buffer where reading started,
                // count holds size of buffer.

                //count = readBytes; // Reassigned
            }

            // These variables have a different meaning depending on the operation; read or write.
            byte[] buffer = GetAsyncBuffer(asyncResult);
            // Offset in buffer where relevant data starts.
            int offset = GetAsyncOffset(asyncResult);
            // Amount of bytes encoding the relevant data (starting from offset).
            int count = GetAsyncCount(asyncResult);

            if (!isWriting)
            {
                count = readBytes;
            }

            // We can assume the async operation succeeded.
            if (buffer != null)
            {
                // HookRegistry.Log("SslStreamHook - {0} - writing", underlyingSocket.GetHashCode());
                dumpServer.PartialData(underlyingSocket, !isWriting, buffer, offset, count, isWrapping: true, singleDecode: false);
            }
            else
            {
                HookRegistry.Log("SslStreamHook - {0} - buffer == null!", underlyingSocket.GetHashCode());
            }


            // Short circuit original method; this prevents executing the method twice.
            _reentrant = false;
            return(OPresult);
        }