diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java index 926691d9c..5d7e4ddb1 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java @@ -8,6 +8,8 @@ import net.mamoe.mirai.network.packet.login.LoginState; import net.mamoe.mirai.task.MiraiTaskManager; import net.mamoe.mirai.utils.LoggerTextFormat; import net.mamoe.mirai.utils.MiraiLogger; +import net.mamoe.mirai.utils.MiraiLoggerKt; +import net.mamoe.mirai.utils.RobotAccount; import net.mamoe.mirai.utils.config.MiraiConfig; import net.mamoe.mirai.utils.config.MiraiConfigSection; import net.mamoe.mirai.utils.setting.MiraiSettingListSection; @@ -16,7 +18,9 @@ import net.mamoe.mirai.utils.setting.MiraiSettings; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.Scanner; +import java.util.concurrent.ExecutionException; /** * @author NaturalHG @@ -174,17 +178,24 @@ public class MiraiServer { getLogger().info("Initializing [Robot]s"); + try { + getAvailableRobot(); + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + } + + /* this.qqs.keySet().stream().map(key -> this.qqs.getSection(key)).forEach(section -> { getLogger().info("Initializing [Robot] " + section.getString("account")); try { Robot robot = new Robot(section); var state = robot.network.tryLogin$mirai_core().get(); //robot.network.tryLogin$mirai_core().whenComplete((state, e) -> { - if (state == LoginState.SUCCEED) { + if (state == LoginState.SUCCESS) { Robot.instances.add(robot); - getLogger().success(" Login Succeed"); + getLogger().success(" Login Succeed"); } else { - getLogger().error(" Login Failed with error " + state); + getLogger().error(" Login Failed with error " + state); robot.close(); } // }).get(); @@ -194,8 +205,42 @@ public class MiraiServer { getLogger().error("Could not load QQ robots config!"); System.exit(1); } - }); + });*/ } + String qqList = "3150499752----1234567890\n" + + "3119292829----987654321\n" + + "2399148773----12345678910\n" + + "3145561616----987654321\n" + + "2374150554----12345678910\n" + + "2375307394----12345678910\n" + + "1531848970----1234567890\n" + + "1947293188----a123456789\n" + + "1771231721----123456789a\n" + + "2401645747----12345678910\n" + + "3338427598----987654321\n" + + "3055657369----1234567890\n" + + "3502771486----987654321\n" + + "1515419818----1234567890\n" + + "2402273360----12345678910\n" + + "3107367848----987654321\n" + + "3487109947----123456789a\n" + + "3489288352----123456789a\n" + + "2385617018----12345678910\n" + + "1251003390----123456789a\n"; + + private Robot getAvailableRobot() throws ExecutionException, InterruptedException { + for (String it : qqList.split("\n")) { + var strings = it.split("----"); + var robot = new Robot(new RobotAccount(Long.parseLong(strings[0]), strings[1]), List.of()); + + if (robot.network.tryLogin$mirai_core().get() == LoginState.SUCCESS) { + MiraiLoggerKt.success(robot, "Login succeed"); + return robot; + } + } + + throw new RuntimeException(); + } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt index c57d595db..c1811de31 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt @@ -90,7 +90,7 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { /** * 仅当 [LoginState] 非 [LoginState.UNKNOWN] 且非 [LoginState.TIMEOUT] 才会调用 [loginHook]. - * 如果要输入验证码, 那么会以参数 [LoginState.VERIFICATION_CODE] 调用 [loginHandler], 登录完成后再以 [LoginState.SUCCEED] 调用 [loginHandler] + * 如果要输入验证码, 那么会以参数 [LoginState.VERIFICATION_CODE] 调用 [loginHandler], 登录完成后再以 [LoginState.SUCCESS] 调用 [loginHandler] * * @param touchingTimeoutMillis 连接每个服务器的 timeout */ @@ -296,7 +296,7 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { private lateinit var token0825: ByteArray private var loginTime: Int = 0 private lateinit var loginIP: String - private var tgtgtKey: ByteArray? = null + private var tgtgtKey: ByteArray = getRandomByteArray(16) private var tlv0105: ByteArray = lazyEncode { it.writeHex("01 05 00 30") @@ -329,8 +329,7 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { this.loginIP = packet.loginIP this.loginTime = packet.loginTime this.token0825 = packet.token0825 - this.tgtgtKey = packet.tgtgtKey - sendPacket(ClientPasswordSubmissionPacket(robot.account.qqNumber, robot.account.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token0825)) + sendPacket(ClientPasswordSubmissionPacket(robot.account.qqNumber, robot.account.password, packet.loginTime, packet.loginIP, this.tgtgtKey!!, packet.token0825)) } } @@ -367,10 +366,14 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { this.token00BA = packet.token00BA if (packet.transmissionCompleted) { - (MiraiServer.getInstance().parentFolder + "VerificationCode.png").writeBytes(this.captchaCache!!) robot notice (CharImageUtil.createCharImg(ImageIO.read(this.captchaCache!!.inputStream()))) - robot notice ("需要验证码登录") - robot notice ("若看不清请查根目录下 VerificationCode.png") + robot notice ("需要验证码登录, 验证码为 4 字母") + try { + (MiraiServer.getInstance().parentFolder + "VerificationCode.png").writeBytes(this.captchaCache!!) + robot notice ("若看不清字符图片, 请查看 Mirai 根目录下 VerificationCode.png") + } catch (e: Exception) { + robot notice "无法写出验证码文件, 请尝试查看以上字符图片" + } robot notice ("若要更换验证码, 请直接回车") val code = Scanner(System.`in`).nextLine() if (code.isEmpty() || code.length != 4) { @@ -391,40 +394,18 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { } //是ClientPasswordSubmissionPacket之后服务器回复的 - is ServerLoginResponseResendPacket -> { + is ServerLoginResponseKeyExchangePacket -> { //if (packet.tokenUnknown != null) { //this.token00BA = packet.token00BA!! //println("token00BA changed!!! to " + token00BA.toUByteArray()) //} - if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) { + if (packet.flag == ServerLoginResponseKeyExchangePacket.Flag.`08 36 31 03`) { this.tgtgtKey = packet.tgtgtKey - sendPacket(ClientLoginResendPacket3104( - robot.account.qqNumber, - robot.account.password, - loginTime, - loginIP, - tgtgtKey!!, - token0825, - when (packet.tokenUnknown != null) { - true -> packet.tokenUnknown!! - false -> this.token00BA - }, - packet._0836_tlv0006_encr - )) + sendPacket(ClientLoginResendPacket3104(robot.account.qqNumber, robot.account.password, loginTime, loginIP, tgtgtKey, token0825, packet.tokenUnknown + ?: this.token00BA, packet.tlv0006)) } else { - sendPacket(ClientLoginResendPacket3106( - robot.account.qqNumber, - robot.account.password, - loginTime, - loginIP, - tgtgtKey!!, - token0825, - when (packet.tokenUnknown != null) { - true -> packet.tokenUnknown!! - false -> this.token00BA - }, - packet._0836_tlv0006_encr - )) + sendPacket(ClientLoginResendPacket3106(robot.account.qqNumber, robot.account.password, loginTime, loginIP, tgtgtKey, token0825, packet.tokenUnknown + ?: token00BA, packet.tlv0006)) } } @@ -446,7 +427,7 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { } is ServerLoginSuccessPacket -> { - socketHandler.loginFuture!!.complete(LoginState.SUCCEED) + socketHandler.loginFuture!!.complete(LoginState.SUCCESS) sendPacket(ClientSKeyRequestPacket(robot.account.qqNumber, sessionKey)) } @@ -467,8 +448,8 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { is ServerVerificationCodePacket.Encrypted -> distributePacket(packet.decrypt()) is ServerLoginResponseVerificationCodeInitPacket.Encrypted -> distributePacket(packet.decrypt()) - is ServerLoginResponseResendPacket.Encrypted -> distributePacket(packet.decrypt(this.tgtgtKey!!)) - is ServerLoginResponseSuccessPacket.Encrypted -> distributePacket(packet.decrypt(this.tgtgtKey!!)) + is ServerLoginResponseKeyExchangePacket.Encrypted -> distributePacket(packet.decrypt(this.tgtgtKey)) + is ServerLoginResponseSuccessPacket.Encrypted -> distributePacket(packet.decrypt(this.tgtgtKey)) is ServerSessionKeyResponsePacket.Encrypted -> distributePacket(packet.decrypt(this.sessionResponseDecryptionKey)) is ServerTouchResponsePacket.Encrypted -> distributePacket(packet.decrypt()) is ServerSKeyResponsePacket.Encrypted -> distributePacket(packet.decrypt(sessionKey)) @@ -489,7 +470,6 @@ class RobotNetworkHandler(private val robot: Robot) : Closeable { override fun close() { this.captchaCache = null - this.tgtgtKey = null this.heartbeatFuture?.cancel(true) this.sKeyRefresherFuture?.cancel(true) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt index c208c07f0..6288a255c 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt @@ -26,6 +26,10 @@ class ClientAccountInfoRequestPacket( it.writeByte(0x00) } } + + override fun getFixedId(): String { + return this.idHex + " ?? ??" + } } @PacketId("00 5C") diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt index 9fcd36304..b9d6c41a8 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt @@ -22,6 +22,10 @@ class ClientHeartbeatPacket( it.writeHex("00 01 00 01") } } + + override fun getFixedId(): String { + return this.idHex + " ?? ??" + } } class ServerHeartbeatResponsePacket(input: DataInputStream) : ServerPacket(input) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt index 30f8c16b3..8a42d9394 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt @@ -23,6 +23,10 @@ class ClientSKeyRequestPacket( it.writeHex("33 00 05 00 08 74 2E 71 71 2E 63 6F 6D 00 0A 71 75 6E 2E 71 71 2E 63 6F 6D 00 0C 71 7A 6F 6E 65 2E 71 71 2E 63 6F 6D 00 0C 6A 75 62 61 6F 2E 71 71 2E 63 6F 6D 00 09 6B 65 2E 71 71 2E 63 6F 6D") } } + + override fun getFixedId(): String { + return this.idHex + " ?? ??" + } } /** diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt index 20c092e92..bb7441db4 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt @@ -5,7 +5,10 @@ import net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket import net.mamoe.mirai.network.packet.login.* -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.TEA +import net.mamoe.mirai.utils.getAllDeclaredFields +import net.mamoe.mirai.utils.hexToBytes +import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream /** @@ -50,11 +53,10 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { "08 36 31 03", "08 36 31 04", "08 36 31 05", "08 36 31 06" -> { when (bytes.size) { - 271, 207 -> return ServerLoginResponseResendPacket.Encrypted(stream, when (idHex) { - "08 36 31 03" -> ServerLoginResponseResendPacket.Flag.`08 36 31 03` - else -> { - MiraiLogger debug ("ServerLoginResponseResendPacketEncrypted: flag=$idHex"); ServerLoginResponseResendPacket.Flag.OTHER - } + 271, 207 -> return ServerLoginResponseKeyExchangePacket.Encrypted(stream, when (idHex) { + "08 36 31 03" -> ServerLoginResponseKeyExchangePacket.Flag.`08 36 31 03` + else -> ServerLoginResponseKeyExchangePacket.Flag.OTHER + }).apply { this.idHex = idHex } 871 -> return ServerLoginResponseVerificationCodeInitPacket.Encrypted(stream).apply { this.idHex = idHex } } @@ -132,14 +134,37 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { } fun decryptBy(key: ByteArray): DataInputStream { - input.goto(14) - return DataInputStream(TEA.decrypt(input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, key).inputStream()) + return decryptAsByteArray(key).dataInputStream() } @ExperimentalUnsignedTypes fun decryptBy(keyHex: String): DataInputStream { return this.decryptBy(keyHex.hexToBytes()) } + + fun decryptBy(key1: ByteArray, key2: ByteArray): DataInputStream { + return TEA.decrypt(this.decryptAsByteArray(key1), key2).dataInputStream(); + } + + @ExperimentalUnsignedTypes + fun decryptBy(key1: String, key2: ByteArray): DataInputStream { + return this.decryptBy(key1.hexToBytes(), key2) + } + + @ExperimentalUnsignedTypes + fun decryptBy(key1: ByteArray, key2: String): DataInputStream { + return this.decryptBy(key1, key2.hexToBytes()) + } + + @ExperimentalUnsignedTypes + fun decryptBy(keyHex1: String, keyHex2: String): DataInputStream { + return this.decryptBy(keyHex1.hexToBytes(), keyHex2.hexToBytes()) + } + + private fun decryptAsByteArray(key: ByteArray): ByteArray { + input.goto(14) + return TEA.decrypt(input.readAllBytes().cutTail(1), key) + } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt index e069a02cc..a6a4efb65 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt @@ -1,7 +1,10 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.ByteArrayDataOutputStream +import net.mamoe.mirai.utils.TEA +import net.mamoe.mirai.utils.hexToBytes +import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream import java.io.IOException @@ -20,7 +23,6 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp var loginTime: Int = 0 lateinit var loginIP: String lateinit var token0825: ByteArray - lateinit var tgtgtKey: ByteArray enum class Type { TYPE_08_25_31_01, @@ -41,7 +43,6 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp loginTime = input.readInt() loginIP = input.readIP() - tgtgtKey = getRandomByteArray(16) } else -> { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt index 5c7c4ae61..02ed9bdae 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt @@ -41,8 +41,8 @@ class ClientPasswordSubmissionPacket( @PacketId("08 36 31 04") @ExperimentalUnsignedTypes -class ClientLoginResendPacket3104(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) - : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv_0006_encr) +class ClientLoginResendPacket3104(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv0006: ByteArray? = null) + : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv0006) @PacketId("08 36 31 05") @ExperimentalUnsignedTypes @@ -51,8 +51,8 @@ class ClientLoginResendPacket3105(qq: Long, password: String, loginTime: Int, lo @PacketId("08 36 31 06") @ExperimentalUnsignedTypes -class ClientLoginResendPacket3106(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) - : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv_0006_encr) +class ClientLoginResendPacket3106(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv0006: ByteArray? = null) + : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv0006) @ExperimentalUnsignedTypes open class ClientLoginResendPacket internal constructor( @@ -63,7 +63,7 @@ open class ClientLoginResendPacket internal constructor( val tgtgtKey: ByteArray, val token0825: ByteArray, val token00BA: ByteArray, - val tlv_0006_encr: ByteArray? = null + val tlv0006: ByteArray? = null ) : ClientPacket() { override fun encode() { this.writeQQ(qq) @@ -74,7 +74,7 @@ open class ClientLoginResendPacket internal constructor( this.write(TEA.encrypt(object : ByteArrayDataOutputStream() { override fun toByteArray(): ByteArray { - this.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825, tlv_0006_encr) + this.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825, tlv0006) this.writeHex("01 10") //tag this.writeHex("00 3C")//length @@ -94,7 +94,7 @@ open class ClientLoginResendPacket internal constructor( * @author Him188moe */ @ExperimentalUnsignedTypes -private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv_0006_encr: ByteArray? = null) { +private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv0006: ByteArray? = null) { //this.writeInt(System.currentTimeMillis().toInt()) this.writeHex("01 12")//tag @@ -107,8 +107,8 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I this.writeQQ(qq) this.writeHex("00 06")//tag this.writeHex("00 78")//length - if (tlv_0006_encr != null) { - this.write(tlv_0006_encr) + if (tlv0006 != null) { + this.write(tlv0006) } else { this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt index 90790bbfb..5f3f8b66f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt @@ -7,7 +7,7 @@ enum class LoginState { /** * 登录成功 */ - SUCCEED, + SUCCESS, /** * 密码错误 diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseKeyExchangePacket.kt similarity index 68% rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseKeyExchangePacket.kt index 94f95378e..5894aad73 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseKeyExchangePacket.kt @@ -1,5 +1,6 @@ package net.mamoe.mirai.network.packet.login +import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.packet.PacketId import net.mamoe.mirai.network.packet.ServerPacket import net.mamoe.mirai.network.packet.goto @@ -7,16 +8,18 @@ import net.mamoe.mirai.utils.TestedSuccessfully import java.io.DataInputStream /** + * 服务器进行加密后返回 tgtgtKey + * * @author NaturalHG */ @PacketId("08 36 31 03") -class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : ServerPacket(input) { +class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Flag) : ServerPacket(input) { enum class Flag { `08 36 31 03`, OTHER, } - lateinit var _0836_tlv0006_encr: ByteArray;//120bytes + lateinit var tlv0006: ByteArray;//120bytes var tokenUnknown: ByteArray? = null lateinit var tgtgtKey: ByteArray//16bytes @@ -26,7 +29,7 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : tgtgtKey = this.input.readNBytes(16)//22 //this.input.skip(2)//25 this.input.goto(25) - _0836_tlv0006_encr = this.input.readNBytes(120) + tlv0006 = this.input.readNBytes(120) when (flag) { Flag.`08 36 31 03` -> { @@ -43,7 +46,10 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : } class Encrypted(input: DataInputStream, private val flag: Flag) : ServerPacket(input) { + @ExperimentalUnsignedTypes @TestedSuccessfully - fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseResendPacket = ServerLoginResponseResendPacket(this.decryptBy(tgtgtKey), flag).setId(this.idHex) + fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseKeyExchangePacket { + return ServerLoginResponseKeyExchangePacket(this.decryptBy(Protocol.shareKey, tgtgtKey), flag).setId(this.idHex) + } } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt index 786391fb8..9b71375d6 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt @@ -1,8 +1,10 @@ package net.mamoe.mirai.network.packet.login import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.network.packet.* -import net.mamoe.mirai.utils.TEA +import net.mamoe.mirai.network.packet.ServerPacket +import net.mamoe.mirai.network.packet.goto +import net.mamoe.mirai.network.packet.readNBytesAt +import net.mamoe.mirai.network.packet.readVarString import net.mamoe.mirai.utils.TestedSuccessfully import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream @@ -53,7 +55,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in @ExperimentalUnsignedTypes fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket { input goto 14 - return ServerLoginResponseSuccessPacket(TEA.decrypt(TEA.decrypt(input.readAllBytes().cutTail(1), Protocol.shareKey), tgtgtKey).dataInputStream()).setId(this.idHex) + return ServerLoginResponseSuccessPacket(this.decryptBy(Protocol.shareKey, tgtgtKey)).setId(this.idHex) } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java index 14a05bfdd..f9a6f7d0a 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java @@ -17,6 +17,7 @@ public final class TEA { private static final long UINT32_MASK = 0xffffffffL; private final long[] mKey; private final Random mRandom; + private final byte[] key; private byte[] mOutput; private byte[] mInBlock; private int mIndexPos; @@ -26,6 +27,7 @@ public final class TEA { private boolean isFirstBlock; public TEA(byte[] key) { + this.key = key; mKey = new long[4]; for (int i = 0; i < 4; i++) { mKey[i] = pack(key, i * 4, 4); @@ -250,6 +252,12 @@ public final class TEA { } public byte[] decrypt(byte[] ciphertext) { - return decrypt(ciphertext, 0, ciphertext.length); + try { + return decrypt(ciphertext, 0, ciphertext.length); + } catch (Exception e) { + System.out.println("Source: " + UtilsKt.toUHexString(ciphertext, " ")); + System.out.println("Key: " + UtilsKt.toUHexString(this.key, " ")); + throw e; + } } } \ No newline at end of file diff --git a/mirai-core/src/test/java/BadQQFilter.kt b/mirai-core/src/test/java/BadQQFilter.kt index fdd5ce1f0..9d67dc6e4 100644 --- a/mirai-core/src/test/java/BadQQFilter.kt +++ b/mirai-core/src/test/java/BadQQFilter.kt @@ -88,4 +88,3 @@ fun main() { println(goodRobotList.joinToString("\n") { it.account.qqNumber.toString() + " " + it.account.password }) } -