/// <summary> /// Encrypt data using MapleStory's AES method /// </summary> /// <param name="IV">IV to use for encryption</param> /// <param name="data">data to encrypt</param> /// <param name="length">length of data</param> /// <param name="key">the AES key to use</param> /// <returns>Crypted data</returns> public static byte[] AESCrypt(byte[] IV, byte[] data, int length, byte[] key) { AesManaged crypto = new AesManaged { KeySize = 256, //in bits Key = key, Mode = CipherMode.ECB // Should be OFB, but this works too }; MemoryStream memStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(memStream, crypto.CreateEncryptor(), CryptoStreamMode.Write); int remaining = length; int llength = 0x5B0; int start = 0; while (remaining > 0) { byte[] myIV = MapleCrypto.multiplyBytes(IV, 4, 4); if (remaining < llength) { llength = remaining; } for (int x = start; x < (start + llength); x++) { if ((x - start) % myIV.Length == 0) { cryptoStream.Write(myIV, 0, myIV.Length); byte[] newIV = memStream.ToArray(); Array.Copy(newIV, myIV, myIV.Length); memStream.Position = 0; } data[x] ^= myIV[(x - start) % myIV.Length]; } start += llength; remaining -= llength; llength = 0x5B4; } try { cryptoStream.Dispose(); memStream.Dispose(); } catch (Exception e) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "Error disposing AES streams" + e); //Console.WriteLine("Error disposing AES streams" + e); } return(data); }
/// <summary> /// Encrypt data using MapleStory's AES method /// </summary> /// <param name="iv">IV to use for encryption</param> /// <param name="data">data to encrypt</param> /// <param name="length">length of data</param> /// <param name="key">the AES key to use</param> /// <returns>Crypted data</returns> public static byte[] AesCrypt(byte[] iv, byte[] data, int length, byte[] key) { var crypto = new AesManaged { KeySize = 256, Key = key, Mode = CipherMode.ECB // Should be OFB, but this works too }; using (var memStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memStream, crypto.CreateEncryptor(), CryptoStreamMode.Write)) { var remaining = length; var size = 0x5B0; var start = 0; while (remaining > 0) { var myIv = MapleCrypto.MultiplyBytes(iv, 4, 4); if (remaining < size) { size = remaining; } for (var x = start; x < start + size; x++) { if ((x - start) % myIv.Length == 0) { cryptoStream.Write(myIv, 0, myIv.Length); var newIv = memStream.ToArray(); Array.Copy(newIv, myIv, myIv.Length); memStream.Position = 0; } data[x] ^= myIv[(x - start) % myIv.Length]; } start += size; remaining -= size; size = 0x5B4; } } } return(data); }
/// <summary> /// Encrypt data using MapleStory's AES method /// </summary> /// <param name="pIV">IV to use for encryption</param> /// <param name="pData">data to encrypt</param> /// <param name="pLength">length of data</param> /// <param name="pKey">the AES key to use</param> /// <returns>Crypted data</returns> public static byte[] aesCrypt(byte[] pIV, byte[] pData, int pLength, byte[] pKey) { AesManaged crypto = new AesManaged { KeySize = 256, Key = pKey, Mode = CipherMode.ECB }; MemoryStream memStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(memStream, crypto.CreateEncryptor(), CryptoStreamMode.Write); int remaining = pLength; int llength = 0x5B0; int start = 0; while (remaining > 0) { byte[] myIV = MapleCrypto.multiplyBytes(pIV, 4, 4); if (remaining < llength) { llength = remaining; } for (int x = start; x < (start + llength); x++) { if ((x - start) % myIV.Length == 0) { cryptoStream.Write(myIV, 0, myIV.Length); byte[] newIV = memStream.ToArray(); Array.Copy(newIV, myIV, myIV.Length); memStream.Position = 0; } pData[x] ^= myIV[(x - start) % myIV.Length]; } start += llength; remaining -= llength; llength = 0x5B4; } try { cryptoStream.Dispose(); memStream.Dispose(); } catch (Exception e) { Console.WriteLine("Error disposing AES streams" + e); } return(pData); }
/// <summary> /// Encrypt data using MapleStory's AES method /// </summary> /// <param name="IV">IV to use for encryption</param> /// <param name="data">data to encrypt</param> /// <param name="length">length of data</param> /// <param name="key">the AES key to use</param> /// <returns>Crypted data</returns> public static byte[] AesCrypt(byte[] IV, byte[] data, int length, byte[] key) { AesManaged crypto = new AesManaged { KeySize = 256, //in bits Key = key, Mode = CipherMode.ECB // Should be OFB, but this works too }; using (MemoryStream memStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream(memStream, crypto.CreateEncryptor(), CryptoStreamMode.Write)) { int remaining = length; int llength = 0x5B0; int start = 0; while (remaining > 0) { byte[] myIV = MapleCrypto.MultiplyBytes(IV, 4, 4); if (remaining < llength) { llength = remaining; } for (int x = start; x < (start + llength); x++) { if ((x - start) % myIV.Length == 0) { cryptoStream.Write(myIV, 0, myIV.Length); byte[] newIV = memStream.ToArray(); Array.Copy(newIV, myIV, myIV.Length); memStream.Position = 0; } data[x] ^= myIV[(x - start) % myIV.Length]; } start += llength; remaining -= llength; llength = 0x5B4; } } } return(data); }
/// <summary> /// Data received event handler /// </summary> /// <param name="iar">IAsyncResult of the data received event</param> private void OnDataReceived(IAsyncResult iar) { SocketInfo socketInfo = (SocketInfo)iar.AsyncState; try { int received = socketInfo.Socket.EndReceive(iar); if (received == 0) { if (OnClientDisconnected != null) { OnClientDisconnected(this); } return; } socketInfo.Index += received; if (socketInfo.Index == socketInfo.DataBuffer.Length) { switch (socketInfo.State) { case SocketInfo.StateEnum.Header: if (socketInfo.NoEncryption) { PacketReader headerReader = new PacketReader(socketInfo.DataBuffer); short packetHeader = headerReader.ReadShort(); socketInfo.State = SocketInfo.StateEnum.Content; socketInfo.DataBuffer = new byte[packetHeader]; socketInfo.Index = 0; WaitForData(socketInfo); } else { PacketReader headerReader = new PacketReader(socketInfo.DataBuffer); byte[] packetHeaderB = headerReader.ToArray(); int packetHeader = headerReader.ReadInt(); short packetLength = (short)MapleCrypto.getPacketLength(packetHeader); if (_type == SessionType.SERVER_TO_CLIENT && !_RIV.checkPacketToServer(BitConverter.GetBytes(packetHeader))) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Packet check failed. Disconnecting client."); //this.Socket.Close(); } socketInfo.State = SocketInfo.StateEnum.Content; socketInfo.DataBuffer = new byte[packetLength]; socketInfo.Index = 0; WaitForData(socketInfo); } break; case SocketInfo.StateEnum.Content: byte[] data = socketInfo.DataBuffer; if (socketInfo.NoEncryption) { socketInfo.NoEncryption = false; PacketReader reader = new PacketReader(data); short version = reader.ReadShort(); string unknown = reader.ReadMapleString(); _SIV = new MapleCrypto(reader.ReadBytes(4), version); _RIV = new MapleCrypto(reader.ReadBytes(4), version); byte serverType = reader.ReadByte(); if (_type == SessionType.CLIENT_TO_SERVER) { OnInitPacketReceived(version, serverType); } OnPacketReceived(new PacketReader(data), true); WaitForData(); } else { _RIV.crypt(data); MapleCustomEncryption.Decrypt(data); if (data.Length != 0 && OnPacketReceived != null) { OnPacketReceived(new PacketReader(data), false); } WaitForData(); } break; } } else { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Warning] Not enough data"); WaitForData(socketInfo); } } catch (ObjectDisposedException) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Session.OnDataReceived: Socket has been closed"); } catch (SocketException se) { if (se.ErrorCode != 10054) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Session.OnDataReceived: " + se); } } catch (Exception e) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Session.OnDataReceived: " + e); } }