예제 #1
0
 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();
     }
 }
예제 #2
0
        /// <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);
                    }
                }*/
            }
        }
예제 #3
0
        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;
        }
예제 #7
0
        /// <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++;
                }
            }
        }
예제 #8
0
 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();
     }
 }
예제 #9
0
        /// <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;
                    }
                }
            }
        }
예제 #10
0
        /// <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));
            }
        }