public static byte[] Serialize(Header header) { using(MemoryStream ms = new MemoryStream()) using(PayloadWriter pw = new PayloadWriter()) { Serializer.Serialize(ms, header); pw.WriteUShort((ushort)ms.Length); pw.WriteBytes(ms.ToArray()); return pw.ToByteArray(); } }
/// <summary> /// Send data to the established connection /// </summary> /// <param name="Message">The data to send</param> /// <param name="Header">The Header to use for adding additional information</param> /// <param name="feature">The Feature that has been used for this Message</param> /// <param name="OpSocket">The OperationalSocket that has been used for this Message</param> internal int SendMessage(IMessage Message, Header Header, Feature feature = null, OperationalSocket OpSocket = null) { lock (SendLock) { if (!Connected) return -1; if (Message == null) throw new ArgumentException("Message cannot be null"); if (Header == null) throw new ArgumentException("Header cannot be null"); ushort HeaderId = OpSocket != null ? OpSocket.Headers.GetHeaderId(Header) : Headers.GetHeaderId(Header); byte[] SerializedHeader = Header.Serialize(Header); uint messageId = OpSocket != null ? OpSocket.MessageHandler.GetMessageId(Message.GetType()) : messageHandler.GetMessageId(Message.GetType()); if (SerializedHeader.Length >= MAX_PACKET_SIZE) throw new ArgumentException("Header length cannot be greater then " + MAX_PAYLOAD); using (MemoryStream outStream = new MemoryStream()) using (PayloadWriter pw = new PayloadWriter(outStream)) { pw.WriteBytes(new byte[HEADER_SIZE], 0, HEADER_SIZE); //reserve space pw.WriteBytes(SerializedHeader); pw.WriteUInteger(messageId); int packetSize = messageHandler.EncryptMessage(this, Message, outStream); if (pw.Length > MAX_PACKET_SIZE) throw new OverflowException("Message size cannot be greater then " + MAX_PACKET_SIZE); int PayloadLength = pw.Length - Connection.HEADER_SIZE; byte CurPacketId = 0; int FeatureId = feature != null ? feature.GetFeatureId() : -1; ushort ConnectionId = OpSocket != null ? OpSocket.ConnectionId : (ushort)0; byte checksum = 0; checksum += (byte)PayloadLength; checksum += CurPacketId; checksum += (byte)ConnectionId; checksum += (byte)HeaderId; checksum += (byte)FeatureId; pw.Position = 0; pw.WriteThreeByteInteger(PayloadLength); //length pw.WriteByte(CurPacketId); //cur packet id pw.WriteUShort(ConnectionId); //Connection Id pw.WriteUShort(HeaderId); //Header Id pw.WriteByte(checksum); pw.WriteInteger(FeatureId); //encrypt the header lock (HeaderEncryption) { HeaderEncryption.Encrypt(pw.GetBuffer(), 0, HEADER_SIZE); byte[] temp = pw.GetBuffer(); headerConfuser.Obfuscate(ref temp, 0); } int SendNum = 0; try { for (int i = 0; i < outStream.Length;) { int len = i + 65535 < outStream.Length ? 65535 : (int)outStream.Length - i; Handle.Send(outStream.GetBuffer(), i, len, SocketFlags.None); i += len; SendNum += len; } } catch (Exception ex) { Disconnect(); return -1; } SysLogger.Log("Send " + outStream.Length, SysLogType.Network); PacketsOut++; DataOut += (ulong)outStream.Length; this.LastPacketSendSW = Stopwatch.StartNew(); return SendNum; } /*using (OptimizedPayloadStream ms = new OptimizedPayloadStream(SerializedHeader, HeaderId, feature, OpSocket)) { ms.Write(BitConverter.GetBytes(messageId), 0, 4); MemoryStream stream = ms.PayloadFrames[ms.PayloadFrames.Count - 1]; int ReservedPos = (int)stream.Position; ms.Write(new byte[3], 0, 3); //reserve space ms.WritingMessage = true; Serializer.Serialize(ms, Message); ms.WritingMessage = false; using (PayloadWriter pw = new PayloadWriter(new MemoryStream(stream.GetBuffer()))) { pw.Position = ReservedPos; //skip MessageId data pw.WriteThreeByteInteger(ms.MessageLength);//Reserved Space + MessageId = 7 } ms.Commit(this); for (int i = 0; i < ms.PayloadFrames.Count; i++) { stream = ms.PayloadFrames[i]; lock (HeaderEncryption) { HeaderEncryption.Encrypt(stream.GetBuffer(), 0, HEADER_SIZE); byte[] temp = stream.GetBuffer(); headerConfuser.Obfuscate(ref temp, 0); } //lock (PayloadEncryption) //{ // PayloadEncryption.Encrypt(stream.GetBuffer(), HEADER_SIZE, (int)stream.Length - HEADER_SIZE); //} Handle.Send(stream.GetBuffer(), 0, (int)stream.Length, SocketFlags.None); } }*/ } }
public byte[] Encrypt(byte[] Data, int Offset, int Length) { lock(AES) { byte[] NewIV = new byte[16]; Frandom.NextBytes(NewIV); this.IV = NewIV; //mask the IV to make it harder to grab the IV while packet sniffing / MITM IvConfuser.Obfuscate(ref NewIV, 0); using (ICryptoTransform Encryptor = AES.CreateEncryptor()) { using(PayloadWriter pw = new PayloadWriter(new System.IO.MemoryStream())) { pw.WriteBytes(NewIV); pw.WriteBytes(Encryptor.TransformFinalBlock(Data, Offset, Length)); return pw.ToByteArray(); } } } }
public byte[] Serialize(object obj) { if (obj == null) { return new byte[] { (byte)ObjectTypes.Null } } ; PayloadWriter pw = new PayloadWriter(); Type ObjectType = obj.GetType(); if (ObjectType == typeof(byte)) { pw.WriteByte((byte)ObjectTypes.Byte); pw.WriteByte((byte)obj); } else if (ObjectType == typeof(byte[])) { byte[] data = (byte[])obj; pw.WriteByte((byte)ObjectTypes.ByteArray); pw.WriteInteger(data.Length); pw.WriteBytes(data); } else if (ObjectType == typeof(short)) { pw.WriteByte((byte)ObjectTypes.Short); pw.WriteShort((short)obj); } else if (ObjectType == typeof(ushort)) { pw.WriteByte((byte)ObjectTypes.UShort); pw.WriteUShort((ushort)obj); } else if (ObjectType == typeof(int)) { pw.WriteByte((byte)ObjectTypes.Int); pw.WriteInteger((int)obj); } else if (ObjectType == typeof(uint)) { pw.WriteByte((byte)ObjectTypes.UINT); pw.WriteUInteger((uint)obj); } else if (ObjectType == typeof(long)) { pw.WriteByte((byte)ObjectTypes.Long); pw.WriteLong((long)obj); } else if (ObjectType == typeof(bool)) { pw.WriteByte((byte)ObjectTypes.Bool); pw.WriteByte((bool)obj ? (byte)1 : (byte)0); } else if (ObjectType == typeof(string)) { pw.WriteByte((byte)ObjectTypes.String); pw.WriteString(obj.ToString()); } else if (ObjectType == typeof(SolidBrush)) { pw.WriteByte((byte)ObjectTypes.SolidBrush); pw.WriteByte(((SolidBrush)obj).Color.A); pw.WriteByte(((SolidBrush)obj).Color.R); pw.WriteByte(((SolidBrush)obj).Color.G); pw.WriteByte(((SolidBrush)obj).Color.B); } else if (ObjectType == typeof(Rectangle)) { pw.WriteByte((byte)ObjectTypes.Rectangle); pw.WriteInteger(((Rectangle)obj).X); pw.WriteInteger(((Rectangle)obj).Y); pw.WriteInteger(((Rectangle)obj).Width); pw.WriteInteger(((Rectangle)obj).Height); } else if (ObjectType == typeof(Size)) { pw.WriteByte((byte)ObjectTypes.Size); pw.WriteInteger(((Size)obj).Width); pw.WriteInteger(((Size)obj).Height); } else if (ObjectType == typeof(Bitmap) || ObjectType == typeof(Image)) { pw.WriteByte((byte)ObjectTypes.Bitmap); lzwCompression.Compress((Bitmap)obj, pw.vStream); } else { MemoryStream ms = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, obj); pw.WriteByte((byte)ObjectTypes.Other); pw.WriteBytes(ms.GetBuffer(), 0, (int)ms.Length); ms.Close(); } return(pw.ToByteArray()); }
public byte[] Serialize(object obj) { if (obj == null) return new byte[] { (byte)ObjectTypes.Null }; PayloadWriter pw = new PayloadWriter(); Type ObjectType = obj.GetType(); if (ObjectType == typeof(byte)) { pw.WriteByte((byte)ObjectTypes.Byte); pw.WriteByte((byte)obj); } else if (ObjectType == typeof(byte[])) { byte[] data = (byte[])obj; pw.WriteByte((byte)ObjectTypes.ByteArray); pw.WriteInteger(data.Length); pw.WriteBytes(data); } else if (ObjectType == typeof(short)) { pw.WriteByte((byte)ObjectTypes.Short); pw.WriteShort((short)obj); } else if (ObjectType == typeof(ushort)) { pw.WriteByte((byte)ObjectTypes.UShort); pw.WriteUShort((ushort)obj); } else if (ObjectType == typeof(int)) { pw.WriteByte((byte)ObjectTypes.Int); pw.WriteInteger((int)obj); } else if (ObjectType == typeof(uint)) { pw.WriteByte((byte)ObjectTypes.UINT); pw.WriteUInteger((uint)obj); } else if (ObjectType == typeof(long)) { pw.WriteByte((byte)ObjectTypes.Long); pw.WriteLong((long)obj); } else if (ObjectType == typeof(bool)) { pw.WriteByte((byte)ObjectTypes.Bool); pw.WriteByte((bool)obj ? (byte)1 : (byte)0); } else if (ObjectType == typeof(string)) { pw.WriteByte((byte)ObjectTypes.String); pw.WriteString(obj.ToString()); } else if (ObjectType == typeof(SolidBrush)) { pw.WriteByte((byte)ObjectTypes.SolidBrush); pw.WriteByte(((SolidBrush)obj).Color.A); pw.WriteByte(((SolidBrush)obj).Color.R); pw.WriteByte(((SolidBrush)obj).Color.G); pw.WriteByte(((SolidBrush)obj).Color.B); } else if (ObjectType == typeof(Rectangle)) { pw.WriteByte((byte)ObjectTypes.Rectangle); pw.WriteInteger(((Rectangle)obj).X); pw.WriteInteger(((Rectangle)obj).Y); pw.WriteInteger(((Rectangle)obj).Width); pw.WriteInteger(((Rectangle)obj).Height); } else if (ObjectType == typeof(Size)) { pw.WriteByte((byte)ObjectTypes.Size); pw.WriteInteger(((Size)obj).Width); pw.WriteInteger(((Size)obj).Height); } else if (ObjectType == typeof(Bitmap) || ObjectType == typeof(Image)) { pw.WriteByte((byte)ObjectTypes.Bitmap); lzwCompression.Compress((Bitmap)obj, pw.vStream); } else { MemoryStream ms = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, obj); pw.WriteByte((byte)ObjectTypes.Other); pw.WriteBytes(ms.GetBuffer(), 0, (int)ms.Length); ms.Close(); } return pw.ToByteArray(); }
/// <summary> /// Serialize the Message to output stream /// </summary> /// <param name="message"></param> /// <param name="TargetStream"></param> /// <returns>The size of the serialzed message</returns> internal int EncryptMessage(Connection conn, IMessage message, MemoryStream TargetStream) { PayloadWriter pw = new PayloadWriter(TargetStream); int PayloadPos = pw.Position; Serializer.Serialize(TargetStream, message); //return (int)TargetStream.Length; #region Security //compress data if (CompressionAlgorithm.QuickLZ == (conn.CompressionAlgorithm & CompressionAlgorithm.QuickLZ)) { UnsafeQuickLZ quickLz = new UnsafeQuickLZ(); byte[] compressed = quickLz.compress(TargetStream.GetBuffer(), (uint)Connection.HEADER_SIZE, (uint)TargetStream.Length - Connection.HEADER_SIZE); if (compressed != null && compressed.Length + Connection.HEADER_SIZE < TargetStream.Length) //only apply compression if it's smaller then the original data { TargetStream.Position = Connection.HEADER_SIZE; TargetStream.Write(compressed, 0, compressed.Length); if (TargetStream.Length != compressed.Length + Connection.HEADER_SIZE) TargetStream.SetLength(compressed.Length + Connection.HEADER_SIZE); } } //encrypt all the data if (EncAlgorithm.HwAES == (conn.EncryptionAlgorithm & EncAlgorithm.HwAES)) { lock (conn.EncAES) { //no need to re-size the stream here, AES will encrypt at the same size or bigger then the stream, so data will be overwritten byte[] encrypted = conn.EncAES.Encrypt(TargetStream.GetBuffer(), Connection.HEADER_SIZE, (int)TargetStream.Length - Connection.HEADER_SIZE); TargetStream.Position = Connection.HEADER_SIZE; TargetStream.Write(encrypted, 0, encrypted.Length); } } if (EncAlgorithm.WopEx == (conn.EncryptionAlgorithm & EncAlgorithm.WopEx)) { lock (conn.PayloadEncryption) { conn.PayloadEncryption.Encrypt(TargetStream.GetBuffer(), Connection.HEADER_SIZE, (int)TargetStream.Length - Connection.HEADER_SIZE); } } #endregion return pw.Length - PayloadPos; }
/// <summary> /// Save the changes and apply Header Information /// </summary> public void Commit(Connection conn) { bool UseFragments = PayloadFrames.Count > 1; int FullLength = 0; byte FragmentId = (byte)(UseFragments ? 1 : 0); //count all the payload, this is the original size for (int i = 0; i < PayloadFrames.Count; i++) { FullLength += (int)PayloadFrames[i].Length - Connection.HEADER_SIZE; } #region Encryption & Compression //compress all the data for (int i = 0; i < PayloadFrames.Count; i++) { MemoryStream stream = PayloadFrames[i]; if (CompressionAlgorithm.QuickLZ == (conn.CompressionAlgorithm & CompressionAlgorithm.QuickLZ)) { UnsafeQuickLZ quickLz = new UnsafeQuickLZ(); byte[] compressed = quickLz.compress(stream.GetBuffer(), (uint)Connection.HEADER_SIZE, (uint)stream.Length - Connection.HEADER_SIZE); if (compressed != null && compressed.Length + Connection.HEADER_SIZE < stream.Length) //only apply compression if it's smaller then the original data { stream.Position = Connection.HEADER_SIZE; stream.Write(compressed, 0, compressed.Length); if (stream.Length != compressed.Length + Connection.HEADER_SIZE) { stream.SetLength(compressed.Length + Connection.HEADER_SIZE); } } } } //encrypt all the data for (int i = 0; i < PayloadFrames.Count; i++) { MemoryStream stream = PayloadFrames[i]; if (EncAlgorithm.HwAES == (conn.EncryptionAlgorithm & EncAlgorithm.HwAES)) { lock (conn.EncAES) { //no need to re-size the stream here, AES will encrypt at the same size or bigger then the stream, so data will be overwritten byte[] encrypted = conn.EncAES.Encrypt(stream.GetBuffer(), Connection.HEADER_SIZE, (int)stream.Length - Connection.HEADER_SIZE); stream.Position = Connection.HEADER_SIZE; stream.Write(encrypted, 0, encrypted.Length); } } if (EncAlgorithm.WopEx == (conn.EncryptionAlgorithm & EncAlgorithm.WopEx)) { lock (conn.PayloadEncryption) { conn.PayloadEncryption.Encrypt(stream.GetBuffer(), Connection.HEADER_SIZE, (int)stream.Length - Connection.HEADER_SIZE); } } } #endregion for (int i = 0; i < PayloadFrames.Count; i++) { PayloadWriter pw = new PayloadWriter(PayloadFrames[i]); pw.Position = 0; //if (pw.Length - Connection.HEADER_SIZE > ushort.MaxValue) // throw new OverflowException(); //should never happen if Write(...) is handled correctly ushort PayloadLength = (ushort)(pw.Length - Connection.HEADER_SIZE); byte CurPacketId = 0; int FeatureId = feature != null?feature.GetFeatureId() : -1; ushort ConnectionId = OpSocket != null ? OpSocket.ConnectionId : (ushort)0; if (i + 1 >= PayloadFrames.Count && UseFragments) { FragmentId += 128; } byte checksum = 0; checksum += (byte)PayloadLength; checksum += FragmentId; checksum += CurPacketId; checksum += (byte)ConnectionId; checksum += (byte)HeaderId; checksum += (byte)FullLength; checksum += (byte)FeatureId; pw.WriteUShort(PayloadLength); //length pw.WriteByte(CurPacketId); //cur packet id pw.WriteUShort(ConnectionId); //Connection Id pw.WriteUShort(HeaderId); //Header Id pw.WriteByte(FragmentId); pw.WriteByte(checksum); pw.WriteThreeByteInteger(FullLength); //the full packet size, mainly used for Fragmentation pw.WriteInteger(FeatureId); if (UseFragments) { FragmentId++; } } }
private static byte[] WriteInstruction(InstructionInfo Instruction) { using (PayloadWriter pw = new PayloadWriter()) using (MemoryStream ms = new MemoryStream()) { Serializer.Serialize(ms, Instruction); pw.WriteByte((byte)ms.Length); pw.WriteBytes(ms.ToArray()); return pw.ToByteArray(); } }
/// <summary> /// Encrypt the data /// </summary> /// <param name="Data">The data to encrypt</param> /// <param name="Offset">The index where the data starts</param> /// <param name="Length">The length to encrypt</param> public void Encrypt(byte[] Data, int Offset, int Length) { lock (EncState) { int OrgLen = Length; Length += Offset; for (int round = 0; round < Rounds; round++) { ulong temp_Value = EncState.IV[EncMode == WopEncMode.Simple ? 0 : EncState.IV_Pos]; //is being used for CBC Mode (Block-Cipher-Chaining Mode) using (PayloadWriter pw = new PayloadWriter(new System.IO.MemoryStream(Data))) { for (int i = Offset, k = 0; i < Length; k++) { pw.vStream.Position = i; int usedsize = 0; if (i + 8 < Length) { ulong OrgValue = BitConverter.ToUInt64(Data, i); usedsize = 8; ulong value = Encrypt_Core_Big(OrgValue, OrgLen, k) ^ temp_Value; pw.WriteULong(value); temp_Value += value; EncState.Seed += (int)OrgValue; } else { byte OrgValue = Data[i]; usedsize = 1; byte value = Encrypt_Core_Small(OrgValue, OrgLen, k); pw.WriteByte(value); EncState.Seed += OrgValue; } i += usedsize; if (EncMode != WopEncMode.Simple) { EncState.Key_Pos += 1; EncState.Salt_Pos += 1; } } } } EncState.IV_Pos = (EncState.IV_Pos + 1) % EncState.IV.Length; switch (EncMode) { case WopEncMode.GenerateNewAlgorithm: { InstructionInfo tempEncCode = null; InstructionInfo tempDecCode = null; FastRandom fastRand = new FastRandom(EncState.Seed); for (int i = 0; i < EncState.Instructions.Length; i++) { GetNextRandomInstruction(fastRand, ref tempEncCode, ref tempDecCode); EncState.Instructions[i] = tempEncCode; } if (UseDynamicCompiler) { EncState.Compile(); } break; } case WopEncMode.ShuffleInstructions: { ShuffleInstructions(EncState.Instructions, EncState.Seed); if (UseDynamicCompiler) { EncState.Compile(); } break; } } } }
/// <summary> /// Generate a random encryption/decryption algorithm /// </summary> /// <param name="Instructions">The max number of instructions to generate, higher=slower</param> /// <param name="EncryptCode"></param> /// <param name="DecryptCode"></param> /// <param name="TestAlgorithm">Test the algorithm for strongness, it will take longer generating the algorithm</param> public static void GenerateCryptoCode(int Seed, int Instructions, ref byte[] EncryptCode, ref byte[] DecryptCode, bool TestAlgorithm = true) { lock (Locky) { FastRandom rnd = new FastRandom(Seed); do { using (PayloadWriter EncPw = new PayloadWriter()) using (PayloadWriter DecPw = new PayloadWriter()) { //generate a random instruction and when generated set the opposide for Decryption for (int i = 0; i < Instructions; i++) { InstructionInfo EncInstruction = null; InstructionInfo DecInstruction = null; GetNextRandomInstruction(rnd, ref EncInstruction, ref DecInstruction); EncPw.WriteBytes(WriteInstruction(EncInstruction)); DecPw.WriteBytes(WriteInstruction(DecInstruction)); } EncryptCode = EncPw.ToByteArray(); DecryptCode = DecPw.ToByteArray(); } } while (TestAlgorithm && IsAlgorithmWeak(EncryptCode, DecryptCode, Seed)); } }