// 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); }
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); }
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); }