diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
index 264533207..afb353be8 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
@@ -14,10 +14,8 @@ import net.mamoe.mirai.network.packet.client.ClientPacket
 import net.mamoe.mirai.network.packet.client.login.*
 import net.mamoe.mirai.network.packet.client.writeHex
 import net.mamoe.mirai.network.packet.server.ServerPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseFailedPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseResendPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseSucceedPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseVerificationCodePacket
+import net.mamoe.mirai.network.packet.server.login.*
+import net.mamoe.mirai.network.packet.server.security.ServerSessionKeyResponsePacketEncrypted
 import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
 import net.mamoe.mirai.util.getRandomKey
 import net.mamoe.mirai.utils.MiraiLogger
@@ -34,12 +32,24 @@ class Robot(val number: Int, private val password: String) {
 
     private var channel: Channel? = null
 
+    private lateinit var serverIP: String;
+
     private lateinit var token00BA: ByteArray
     private lateinit var token0825: ByteArray
     private var loginTime: Int = 0
     private lateinit var loginIP: String
     private var tgtgtKey: ByteArray? = null
 
+    /**
+     * Kind of key, similar to sessionKey
+     */
+    private lateinit var tlv0105: ByteArray
+    private lateinit var sessionKey: ByteArray
+    /**
+     * Kind of key, similar to sessionKey
+     */
+    private lateinit var _0828_rec_decr_key: ByteArray
+
     @ExperimentalUnsignedTypes
     private var md5_32: ByteArray = getRandomKey(32)
 
@@ -51,23 +61,13 @@ class Robot(val number: Int, private val password: String) {
             is ServerTouchResponsePacket -> {
                 if (packet.serverIP != null) {//redirection
                     connect(packet.serverIP!!)
-                    sendPacket(ClientServerRedirectionPacket(
-                            serverIP = packet.serverIP!!,
-                            qq = number
-                    ))
+                    sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, number))
                 } else {//password submission
                     this.loginIP = packet.loginIP
                     this.loginTime = packet.loginTime
                     this.token0825 = packet.token
                     this.tgtgtKey = packet.tgtgtKey
-                    sendPacket(ClientPasswordSubmissionPacket(
-                            qq = this.number,
-                            password = this.password,
-                            loginTime = packet.loginTime,
-                            loginIP = packet.loginIP,
-                            token0825 = packet.token,
-                            tgtgtKey = packet.tgtgtKey
-                    ))
+                    sendPacket(ClientPasswordSubmissionPacket(this.number, this.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token))
                 }
             }
 
@@ -82,46 +82,29 @@ class Robot(val number: Int, private val password: String) {
                 this.token00BA = packet.token00BA
                 if (packet.unknownBoolean != null && packet.unknownBoolean!!) {
                     this.sequence = 1
-                    sendPacket(ClientLoginVerificationCodePacket(
-                            qq = this.number,
-                            token0825 = this.token0825,
-                            token00BA = this.token00BA,
-                            sequence = this.sequence
-                    ))
+                    sendPacket(ClientLoginVerificationCodePacket(this.number, this.token0825, this.sequence, this.token00BA))
                 }
 
             }
 
             is ServerLoginResponseSucceedPacket -> {
-
+                this._0828_rec_decr_key = packet._0828_rec_decr_key
+                sendPacket(ClientLoginSucceedConfirmationPacket(this.number, this.serverIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105))
             }
 
             //这个有可能是客户端发送验证码之后收到的回复验证码是否正确?
             is ServerLoginResponseResendPacket -> {
                 if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) {
                     this.tgtgtKey = packet.tgtgtKey
-                    sendPacket(ClientLoginResendPacket3104(
-                            tgtgtKey = packet.tgtgtKey,
-                            token00BA = packet.token,
-                            qq = this.number,
-                            password = this.password,
-                            loginIP = this.loginIP,
-                            loginTime = this.loginTime,
-                            token0825 = this.token0825
-                    ))
+                    sendPacket(ClientLoginResendPacket3104(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA))
                 } else {
-                    sendPacket(ClientLoginResendPacket3106(
-                            tgtgtKey = packet.tgtgtKey,
-                            token00BA = packet.token,
-                            qq = this.number,
-                            password = this.password,
-                            loginIP = this.loginIP,
-                            loginTime = this.loginTime,
-                            token0825 = this.token0825
-                    ))
+                    sendPacket(ClientLoginResendPacket3106(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA))
                 }
             }
 
+            is ServerLoginResponseSucceedPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!))
+            is ServerSessionKeyResponsePacketEncrypted -> onPacketReceived(packet.decrypt(this._0828_rec_decr_key))
+
             else -> throw IllegalStateException()
         }
 
@@ -140,14 +123,15 @@ class Robot(val number: Int, private val password: String) {
 
     @ExperimentalUnsignedTypes
     @Throws(InterruptedException::class)
-    fun connect(host: String, port: Int = 8000) {
+    fun connect(ip: String, port: Int = 8000) {
+        this.serverIP = ip;
         val group = NioEventLoopGroup()
         try {
             val b = Bootstrap()
 
             b.group(group)
                     .channel(NioSocketChannel::class.java)
-                    .remoteAddress(InetSocketAddress(host, port))
+                    .remoteAddress(InetSocketAddress(ip, port))
                     .handler(object : ChannelInitializer<SocketChannel>() {
                         @Throws(Exception::class)
                         override fun initChannel(ch: SocketChannel) {
@@ -163,7 +147,7 @@ class Robot(val number: Int, private val password: String) {
                                             Reader.init()
                                             remaining
                                         }*/
-                                        this@Robot.onPacketReceived(ServerPacket.ofByteArray(bytes, tgtgtKey))
+                                        this@Robot.onPacketReceived(ServerPacket.ofByteArray(bytes))
                                     } catch (e: Exception) {
                                         MiraiLogger.catching(e)
                                     }
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
index b2c0002b8..3539b77c9 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
@@ -5,6 +5,7 @@ import net.mamoe.mirai.network.packet.PacketId
 import net.mamoe.mirai.network.packet.client.*
 import net.mamoe.mirai.util.ByteArrayDataOutputStream
 import net.mamoe.mirai.util.TEACryptor
+import net.mamoe.mirai.util.getRandomKey
 import net.mamoe.mirai.util.hexToBytes
 
 /**
@@ -33,29 +34,14 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password:
     }
 }
 
-/**
- * Dispose_0836
- *
- * @author Him188moe @ Mirai Project
- */
 @PacketId("08 36 31 04")
 @ExperimentalUnsignedTypes
 class ClientLoginResendPacket3104(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA)
 
-/**
- * Dispose_0836
- *
- * @author Him188moe @ Mirai Project
- */
 @PacketId("08 36 31 06")
 @ExperimentalUnsignedTypes
 class ClientLoginResendPacket3106(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA)
 
-/**
- * Dispose_0836
- *
- * @author Him188moe @ Mirai Project
- */
 @ExperimentalUnsignedTypes
 open class ClientLoginResendPacket(val qq: Int, val password: String, val loginTime: Int, val loginIP: String, val tgtgtKey: ByteArray, val token0825: ByteArray, val token00BA: ByteArray) : ClientPacket() {
     override fun encode() {
@@ -82,6 +68,57 @@ open class ClientLoginResendPacket(val qq: Int, val password: String, val loginT
     }
 }
 
+@ExperimentalUnsignedTypes
+@PacketId("08 28 04 34")//todo
+class ClientLoginSucceedConfirmationPacket(
+        private val qq: Int,
+        private val serverIp: String,
+        private val md5_32: ByteArray,
+        private val token38: ByteArray,
+        private val token88: ByteArray,
+        private val encryptionKey: ByteArray,
+        private val tlv0105: ByteArray
+) : ClientPacket() {
+    override fun encode() {
+        this.writeQQ(qq)
+        this.writeHex("02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A")
+        this.writeHex("00 38")
+        this.write(token38)
+        this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
+            override fun toByteArray(): ByteArray {
+                this.writeHex("00 07 00 88")
+                this.write(token88)
+                this.writeHex("00 0C 00 16 00 02 00 00 00 00 00 00 00 00 00 00")
+                this.writeIP(serverIp)
+                this.writeHex("1F 40 00 00 00 00 00 15 00 30 00 01")//fix1
+                this.writeHex("01 92 A5 D2 59 00 10 54 2D CF 9B 60 BF BB EC 0D D4 81 CE 36 87 DE 35 02 AE 6D ED DC 00 10 ")
+                this.writeHex(Protocol._0836fix)
+                this.writeHex("00 36 00 12 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00")
+                this.writeHex(Protocol._0825data0)
+                this.writeHex(Protocol._0825data2)
+                this.writeQQ(qq)
+                this.writeHex("00 00 00 00 00 1F 00 22 00 01")
+                this.writeHex("1A 68 73 66 E4 BA 79 92 CC C2 D4 EC 14 7C 8B AF 43 B0 62 FB 65 58 A9 EB 37 55 1D 26 13 A8 E5 3D")//device ID
+                this.write(tlv0105)
+                this.writeHex("01 0B 00 85 00 02")
+                this.writeHex("B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C")//fix2
+                this.write(getRandomKey(1))
+                this.writeHex("10 00 00 00 00 00 00 00 02")
+
+                //fix3
+                this.writeHex("00 63 3E 00 63 02 04 03 06 02 00 04 00 52 D9 00 00 00 00 A9 58 3E 6D 6D 49 AA F6 A6 D9 33 0A E7 7E 36 84 03 01 00 00 68 20 15 8B 00 00 01 02 00 00 03 00 07 DF 00 0A 00 0C 00 01 00 04 00 03 00 04 20 5C 00")
+                this.write(md5_32)
+                this.writeHex("68")
+
+                this.writeHex("00 00 00 00 00 2D 00 06 00 01")
+                this.writeIP("127.0.0.1")//本地IP地址? todo test that
+
+                return super.toByteArray()
+            }
+        }.toByteArray(), encryptionKey))
+    }
+}
+
 /**
  * @author Him188moe @ Mirai Project
  */
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
index a0dd764e9..ef7c60590 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
@@ -3,7 +3,7 @@ package net.mamoe.mirai.network.packet.server
 import net.mamoe.mirai.network.packet.Packet
 import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseFailedPacket
 import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseResendPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseSucceedPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseSucceedPacketEncrypted
 import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseVerificationCodePacket
 import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
 import net.mamoe.mirai.util.toHexString
@@ -18,7 +18,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
 
     companion object {
 
-        fun ofByteArray(bytes: ByteArray, tgtgtKey: ByteArray?): ServerPacket {
+        fun ofByteArray(bytes: ByteArray): ServerPacket {
 
             val stream = DataInputStream(bytes.inputStream())
 
@@ -38,7 +38,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
                     }
 
                     if (bytes.size > 700) {
-                        return ServerLoginResponseSucceedPacket(stream)
+                        return ServerLoginResponseSucceedPacketEncrypted(stream)
                     }
 
                     return ServerLoginResponseFailedPacket(when (bytes.size) {
@@ -85,3 +85,6 @@ fun DataInputStream.readIP(): String {
     }
     return buff
 }
+
+
+fun ByteArray.dataInputStream(): DataInputStream = DataInputStream(this.inputStream())
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt
deleted file mode 100644
index 5b8895ad8..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.mamoe.mirai.network.packet.server.login
-
-/**
- * @author Him188moe @ Mirai Project
- */
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
index ed2dce5ae..6f02496c8 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
@@ -2,6 +2,7 @@ package net.mamoe.mirai.network.packet.server.login
 
 import net.mamoe.mirai.network.Protocol
 import net.mamoe.mirai.network.packet.server.ServerPacket
+import net.mamoe.mirai.network.packet.server.dataInputStream
 import net.mamoe.mirai.util.TEACryptor
 import net.mamoe.mirai.util.hexToBytes
 import net.mamoe.mirai.util.hexToShort
@@ -11,49 +12,51 @@ import java.io.DataInputStream
  * @author Him188moe @ Mirai Project
  * @author NaturalHG @ Mirai Project
  */
-class ServerLoginResponseSucceedPacket(input: DataInputStream, val tgtgtKey: ByteArray) : ServerPacket(input) {
+class ServerLoginResponseSucceedPacket(input: DataInputStream) : ServerPacket(input) {
     lateinit var _0828_rec_decr_key: ByteArray
     var age: Int = 0
     var gender: Boolean = false//from 1byte
     lateinit var nick: String
     lateinit var clientKey: String
 
+    lateinit var token38: ByteArray
+    lateinit var token88: ByteArray
+    lateinit var encryptionKey: ByteArray
+
 
     @ExperimentalUnsignedTypes
     override fun decode() {
-        input.skip(21)
-        val data = input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }//Drop tail
 
-        val decryptedData = TEACryptor.decrypt(TEACryptor.decrypt(data, Protocol.shareKey.hexToBytes()), tgtgtKey);
-
-
-        DataInputStream(decryptedData.inputStream()).let {
-            //换成 readShort
-
-            it.skip(212)
-            val msgLength = when (it.readShort()) {
+        this.input.skip(141)//取文本中间 (data, 141 * 3 + 1, 5)
+        val msgLength = when (this.input.readShort()) {
                 "01 07".hexToShort() -> 0
                 "00 33".hexToShort() -> 28 * 3
                 "01 10".hexToShort() -> 64 * 3
                 else -> throw IllegalStateException()
             }
 
-            age = it.readShort(取文本中间(it, 取文本长度(it) - 82, 5)).toBoolean()
-            gender = it.readByte(取文本中间(it, 取文本长度(it) - 94, 2))
+        _0828_rec_decr_key = 取文本中间(data, 514 + msgLength, 47)
+        val nickLength = HexToDec(取文本中间(data, 1873 + msgLength, 2))
+        nick = 转_Ansi文本(取文本中间(data, 1876 + msgLength, 3 * nickLength - 1))
+        age = HexToDec(取文本中间(data, 取文本长度(data) - 82, 5))
+        gender = 取文本中间(data, 取文本长度(data) - 94, 2)
+        clientKey = 删全部空(取文本中间(data, 484 * 3 + msgLength + 1, 112 * 3 - 1))
 
-            var position = ((514 + msgLength) / 2 - 212 - 2).toLong();
-            it.skip(position)
-            _0828_rec_decr_key = it.readNBytes(13)
-            it.skip((1873 + msgLength) / 2 - position)
-            position += (1873 + msgLength) / 2
-
-            nick = it.readNBytes(it.readByte().toInt()).toString()
-
-
-            clientKey = it.readBytes(取文本中间(it, 484 * 3 + msgLength + 1, 112 * 3 - 1))
-        }
-
-
-        //SendUdp (Construct_0828 (“04 34”, 取文本中间 (data, 76, 167), 取文本中间 (data, 568 + msg_length, 407), 取文本中间 (data, 22, 47)))
+        token38 = 取文本中间(data, 76, 167)
+        token88 = 取文本中间(data, 568 + msgLength, 407)
+        encryptionKey = 取文本中间(data, 22, 47)
     }
-}
\ No newline at end of file
+}
+
+class ServerLoginResponseSucceedPacketEncrypted(input: DataInputStream) : ServerPacket(input) {
+    override fun decode() {
+
+    }
+
+    @ExperimentalUnsignedTypes
+    fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSucceedPacket {//todo test
+        this.input.skip(14)
+        return ServerLoginResponseSucceedPacket(TEACryptor.decrypt(TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, Protocol.shareKey.hexToBytes()), tgtgtKey).dataInputStream());
+        //TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
+    }
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/security/ServerSessionKeyResponsePacketEncrypted.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/security/ServerSessionKeyResponsePacketEncrypted.kt
new file mode 100644
index 000000000..7a7c20e0a
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/security/ServerSessionKeyResponsePacketEncrypted.kt
@@ -0,0 +1,57 @@
+package net.mamoe.mirai.network.packet.server.security
+
+import net.mamoe.mirai.network.packet.server.ServerPacket
+import net.mamoe.mirai.network.packet.server.dataInputStream
+import net.mamoe.mirai.util.TEACryptor
+import java.io.DataInputStream
+
+/**
+ * Dispose_0828
+ *
+ * @author Him188moe @ Mirai Project
+ */
+class ServerSessionKeyResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
+    override fun decode() {
+        var data = this.input.readAllBytes();
+        when (data.size) {
+            407 -> {
+            }
+
+            439 -> {
+
+            }
+
+            527 -> {
+
+            }
+            else -> {
+            }
+        }
+
+                .判断开始(length = 407)
+        g_sessionKey = 取文本中间 (data, 76, 47)
+        .判断(length = 439)
+        g_sessionKey = 取文本中间 (data, 190, 47)
+        .判断(length = 527)
+        g_sessionKey = 取文本中间 (data, 190, 47)
+        g_tlv0105 = “01 05 00 88 00 01 01 02 ” + “00 40 02 01 03 3C 01 03 00 00 ” + 取文本中间 (data, 取文本长度 (data) - 367, 167) + “ 00 40 02 02 03 3C 01 03 00 00 ” + 取文本中间 (data, 取文本长度 (data) - 166, 167)
+
+    }
+}
+
+/**
+ * Encrypted using []0828_rec_decr_key], decrypting in Robot
+ *
+ * @author Him188moe @ Mirai Project
+ */
+class ServerSessionKeyResponsePacketEncrypted(inputStream: DataInputStream) : ServerPacket(inputStream) {
+    override fun decode() {
+
+    }
+
+    fun decrypt(_0828_rec_decr_key: ByteArray): ServerSessionKeyResponsePacket {//todo test
+        this.input.skip(14)
+        return ServerSessionKeyResponsePacket(TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, _0828_rec_decr_key).dataInputStream());
+        //TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
+    }
+}
\ No newline at end of file