예제 #1
0
        public MapleStream(bool pOutbound, ushort pBuild, byte pLocale, byte[] pIV, byte pSubVersion)
        {
            mOutbound = pOutbound;
            Build = pBuild;
            Locale = pLocale;

            if (mOutbound)
                mAES = new MapleAES(Build, Locale, pIV, pSubVersion);
            else
                mAES = new MapleAES((ushort)(0xFFFF - Build), Locale, pIV, pSubVersion);

            if ((Locale == MapleLocale.TESPIA && Build == 40) ||
                (Locale == MapleLocale.SOUTH_EAST_ASIA && Build == 15))
            {
                // WvsBeta
                _transformMethod = TransformMethod.MAPLE_CRYPTO | TransformMethod.SHIFT_IV;
                _usesByteHeader = true;
            }
            else if (Locale == MapleLocale.KOREA_TEST && Build == 255)
            {
                // KMSB (Modified client)
                _transformMethod = TransformMethod.OLD_KMS_CRYPTO | TransformMethod.SHIFT_IV_OLD;
                _usesByteHeader = true;
                _usesOldHeader = true;
            }
            else if (
                Locale == MapleLocale.TAIWAN ||
                Locale == MapleLocale.CHINA ||
                Locale == MapleLocale.TESPIA ||
                Locale == MapleLocale.JAPAN ||
                (Locale == MapleLocale.GLOBAL && (short)Build >= 149) ||
                (Locale == MapleLocale.KOREA && Build >= 221) ||
                (Locale == MapleLocale.SOUTH_EAST_ASIA && Build >= 144) ||
                (Locale == MapleLocale.EUROPE && Build >= 115))
            {
                // TWMS / CMS / CMST / JMS / GMS (>= 149)
                _transformMethod = TransformMethod.AES | TransformMethod.SHIFT_IV;
            }
            else if (Locale == MapleLocale.KOREA || Locale == MapleLocale.KOREA_TEST)
            {
                // KMS / KMST
                _transformMethod = TransformMethod.KMS_CRYPTO;
            }
            else
            {
                // All others lol
                _transformMethod = TransformMethod.AES | TransformMethod.MAPLE_CRYPTO | TransformMethod.SHIFT_IV;
            }

            Console.WriteLine("Using transform methods: {0}", _transformMethod);
        }
예제 #2
0
        public MaplePacket Read(DateTime pTransmitted, bool bMaple2)
        {
            if (mCursor < _expectedDataSize)
            {
                return(null);
            }
            if (bMaple2)
            {
                if (DecodeSeqBase(IV) != Build)
                {
                    //throw new Exception("Failed to confirm packet header");
                    Console.WriteLine("ERROR: Failed to confirm packet header!");
                }
            }
            else
            {
                if (!mAES.ConfirmHeader(mBuffer, 0))
                {
                    throw new Exception("Failed to confirm packet header");
                }
            }

            int headerLength = bMaple2 ? 6 : MapleAES.GetHeaderLength(mBuffer, mCursor, _usesOldHeader);

            _expectedDataSize = headerLength;
            if (mCursor < headerLength)
            {
                return(null);
            }

            int packetSize = MapleAES.GetPacketLength(mBuffer, mCursor, _usesOldHeader, bMaple2);

            _expectedDataSize = packetSize + headerLength;
            if (mCursor < (packetSize + headerLength))
            {
                return(null);
            }

            byte[] packetBuffer = new byte[packetSize];
            Buffer.BlockCopy(mBuffer, headerLength, packetBuffer, 0, packetSize);

            uint preDecodeIV;

            if (bMaple2)
            {
                preDecodeIV = IV;

                mCrypt.Decrypt(packetBuffer, packetSize, BlockIV, IV);
                ShiftIV();
            }
            else
            {
                preDecodeIV = BitConverter.ToUInt32(mAES.mIV, 0);
                Decrypt(packetBuffer, _transformMethod);
            }

            var postDecodeIV = bMaple2 ? IV : BitConverter.ToUInt32(mAES.mIV, 0);

            mCursor -= _expectedDataSize;
            if (mCursor > 0)
            {
                Buffer.BlockCopy(mBuffer, _expectedDataSize, mBuffer, 0, mCursor);
            }
            ushort opcode;

            if (_usesByteHeader)
            {
                opcode = (ushort)(packetBuffer[0]);
                Buffer.BlockCopy(packetBuffer, 1, packetBuffer, 0, packetSize - 1);
                Array.Resize(ref packetBuffer, packetSize - 1);
            }
            else
            {
                opcode = (ushort)(packetBuffer[0] | (packetBuffer[1] << 8));
                Buffer.BlockCopy(packetBuffer, 2, packetBuffer, 0, packetSize - 2);
                Array.Resize(ref packetBuffer, packetSize - 2);
            }

            _expectedDataSize = bMaple2 ? 6 : 4;

            Definition definition = Config.Instance.GetDefinition(Build, Locale, mOutbound, opcode);

            return(new MaplePacket(pTransmitted, mOutbound, Build, Locale, opcode, definition == null ? "" : definition.Name, packetBuffer, preDecodeIV, postDecodeIV));
        }
예제 #3
0
        public MaplePacket Read(DateTime pTransmitted)
        {
            if (mCursor < _expectedDataSize)
            {
                return(null);
            }
            if (!mAES.ConfirmHeader(mBuffer, 0))
            {
                mCursor -= lastAddedLength;
                //return null;
                throw new Exception("Failed to confirm packet header");
            }

            int headerLength = MapleAES.GetHeaderLength(mBuffer, mCursor, _usesOldHeader);

            _expectedDataSize = headerLength;
            if (mCursor < headerLength)
            {
                return(null);
            }

            int packetSize = MapleAES.GetPacketLength(mBuffer, mCursor, _usesOldHeader);

            _expectedDataSize = packetSize + headerLength;
            if (mCursor < (packetSize + headerLength))
            {
                return(null);
            }

            byte[] packetBuffer = new byte[packetSize];
            Buffer.BlockCopy(mBuffer, headerLength, packetBuffer, 0, packetSize);

            var preDecodeIV = BitConverter.ToUInt32(mAES.mIV, 0);

            Decrypt(packetBuffer, _transformMethod);

            var postDecodeIV = BitConverter.ToUInt32(mAES.mIV, 0);

            mCursor -= _expectedDataSize;
            if (mCursor > 0)
            {
                Buffer.BlockCopy(mBuffer, _expectedDataSize, mBuffer, 0, mCursor);
            }
            ushort opcode;

            if (_usesByteHeader)
            {
                opcode = (ushort)(packetBuffer[0]);
                Buffer.BlockCopy(packetBuffer, 1, packetBuffer, 0, packetSize - 1);
                Array.Resize(ref packetBuffer, packetSize - 1);
            }
            else
            {
                opcode = (ushort)(packetBuffer[0] | (packetBuffer[1] << 8));

                Buffer.BlockCopy(packetBuffer, 2, packetBuffer, 0, packetSize - 2);
                Array.Resize(ref packetBuffer, packetSize - 2);
            }

            _expectedDataSize = 4;

            Definition definition = Config.Instance.GetDefinition(Build, Locale, mOutbound, opcode);

            return(new MaplePacket(pTransmitted, mOutbound, Build, Locale, opcode, definition == null ? "" : definition.Name, packetBuffer, preDecodeIV, postDecodeIV));
        }
예제 #4
0
        public MapleStream(bool pOutbound, ushort pBuild, byte pLocale, byte[] pIV, byte pSubVersion, bool bLoginSv)
        {
            mOutbound = pOutbound;
            mLoginSv  = bLoginSv;
            Build     = pBuild;
            Locale    = pLocale;

            if (mOutbound)
            {
                mAES = new MapleAES(Build, Locale, pIV, pSubVersion);
            }
            else
            {
                mAES = new MapleAES((ushort)(0xFFFF - Build), Locale, pIV, pSubVersion);
            }

            if ((Locale == MapleLocale.TESPIA && Build == 40) ||
                (Locale == MapleLocale.SOUTH_EAST_ASIA && Build == 15))
            {
                // WvsBeta
                _transformMethod = TransformMethod.MAPLE_CRYPTO | TransformMethod.SHIFT_IV;
                _usesByteHeader  = true;
            }
            else if (Locale == MapleLocale.KOREA_TEST && Build == 255)
            {
                // KMSB (Modified client)
                _transformMethod = TransformMethod.OLD_KMS_CRYPTO | TransformMethod.SHIFT_IV_OLD;
                _usesByteHeader  = true;
                _usesOldHeader   = true;
            }
            else if (
                Locale == MapleLocale.TAIWAN ||
                Locale == MapleLocale.CHINA ||
                Locale == MapleLocale.TESPIA ||
                Locale == MapleLocale.JAPAN ||
                (Locale == MapleLocale.GLOBAL && (short)Build >= 149) ||
                (Locale == MapleLocale.KOREA && Build >= 221) ||
                (Locale == MapleLocale.SOUTH_EAST_ASIA && Build >= 144) ||
                (Locale == MapleLocale.EUROPE && Build >= 115))
            {
                // TWMS / CMS / CMST / JMS / GMS (>= 149)
                _transformMethod = TransformMethod.AES | TransformMethod.SHIFT_IV;
                // GMS (>= 186)
                if (Locale == MapleLocale.GLOBAL && Build >= 186)
                {
                    _transformMethod |= TransformMethod.CIG;
                }
            }
            else if (Locale == MapleLocale.KOREA || Locale == MapleLocale.KOREA_TEST)
            {
                // KMS / KMST
                _transformMethod = TransformMethod.KMS_CRYPTO;
            }
            else
            {
                // All others lol
                _transformMethod = TransformMethod.AES | TransformMethod.MAPLE_CRYPTO | TransformMethod.SHIFT_IV;
            }

            Console.WriteLine("Using transform methods: {0}", _transformMethod);
        }
예제 #5
0
        public MaplePacket Read(DateTime pTransmitted)
        {
            if (mCursor < _expectedDataSize)
            {
                return(null);
            }
            if (!mAES.ConfirmHeader(mBuffer, 0))
            {
                throw new Exception("Failed to confirm packet header");
            }

            int headerLength = MapleAES.GetHeaderLength(mBuffer, mCursor, _usesOldHeader);

            _expectedDataSize = headerLength;
            if (mCursor < headerLength)
            {
                return(null);
            }

            int packetSize = MapleAES.GetPacketLength(mBuffer, mCursor, _usesOldHeader);

            _expectedDataSize = packetSize + headerLength;
            if (mCursor < (packetSize + headerLength))
            {
                return(null);
            }

            byte[] packetBuffer = new byte[packetSize];
            Buffer.BlockCopy(mBuffer, headerLength, packetBuffer, 0, packetSize);

            var preDecodeIV = BitConverter.ToUInt32(mAES.mIV, 0);

            Decrypt(packetBuffer, _transformMethod);

            var postDecodeIV = BitConverter.ToUInt32(mAES.mIV, 0);

            mCursor -= _expectedDataSize;
            if (mCursor > 0)
            {
                Buffer.BlockCopy(mBuffer, _expectedDataSize, mBuffer, 0, mCursor);
            }
            ushort opcode;

            if (_usesByteHeader)
            {
                opcode = (ushort)(packetBuffer[0]);
                Buffer.BlockCopy(packetBuffer, 1, packetBuffer, 0, packetSize - 1);
                Array.Resize(ref packetBuffer, packetSize - 1);
            }
            else
            {
                opcode = (ushort)(packetBuffer[0] | (packetBuffer[1] << 8));
                Buffer.BlockCopy(packetBuffer, 2, packetBuffer, 0, packetSize - 2);
                Array.Resize(ref packetBuffer, packetSize - 2);
            }

            _expectedDataSize = 4;

            Definition definition = null;

            // Detect OpcodeEncryption Packet
            if (packetBuffer.Length == (8 + 1 + short.MaxValue)) // 32776
            {
                int blockSize  = BitConverter.ToInt32(packetBuffer, 0);
                int bufferSize = BitConverter.ToInt32(packetBuffer, 4);
                if (blockSize == 4 && bufferSize == (1 + short.MaxValue))
                {
                    Console.WriteLine("Recv OpcodeEncryption Packet with Opcode:0x{0:X} | BlockSize:{1} | BufferSize:{2}", opcode, blockSize, bufferSize);

                    OpcodeEncryptedEventArgs recvOpcodeEventArgs = new OpcodeEncryptedEventArgs();
                    recvOpcodeEventArgs.OpcodeEncrypted  = true;
                    recvOpcodeEventArgs.EncryptedOpcodes = PopulateEncryptedOpcode(packetBuffer, bufferSize);
                    OnRecvOpcodeEncryptPacket(recvOpcodeEventArgs);

                    // Generate OpcodeEncryption packet
                    {
                        definition = Config.Instance.GetDefinition(Build, Locale, mOutbound, opcode);
                        if (definition == null)
                        {
                            definition          = new Definition();
                            definition.Outbound = mOutbound;
                            definition.Locale   = Locale;
                            definition.Opcode   = opcode;
                            definition.Name     = "Opcode Encryption";
                            definition.Build    = Build;
                            DefinitionsContainer.Instance.SaveDefinition(definition);
                        }

                        var filename = Helpers.GetScriptPath(Locale, Build, mOutbound, opcode);
                        Helpers.MakeSureFileDirectoryExists(filename);

                        // Create main script
                        if (!File.Exists(filename))
                        {
                            string contents = @"
using (ScriptAPI) {
    AddInt(""Block Size"");
    AddInt(""Buffer Size"");
    AddByte(""Unknown"");
    AddField(""Buffer With Encrypted Opcodes"", 32767);
}
";
                            File.WriteAllText(filename, contents);
                        }
                    }
                }
            }

            // Get the real opcode
            if (OpcodeEncrypted && mOutbound && EncryptedOpcodes != null && EncryptedOpcodes.ContainsKey(opcode))
            {
                opcode = EncryptedOpcodes[opcode].RealOp;
            }

            definition = Config.Instance.GetDefinition(Build, Locale, mOutbound, opcode);
            return(new MaplePacket(pTransmitted, mOutbound, Build, Locale, opcode, definition == null ? "" : definition.Name, packetBuffer, preDecodeIV, postDecodeIV));
        }
예제 #6
0
 public MapleStream(bool pOutbound, ushort pBuild, byte pLocale, byte[] pIV)
 {
     mOutbound = pOutbound;
     mAES = new MapleAES(pBuild, pLocale, pIV);
 }