diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt index baefa2f31..a238f8734 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt @@ -111,7 +111,7 @@ internal open class QQAndroidClient( class C2cMessageSyncData { var syncCookie = EMPTY_BYTE_ARRAY var pubAccountCookie = EMPTY_BYTE_ARRAY - var syncFlag: Int = 2 + var syncFlag: Int = 0 var msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt index bda6e2f5a..91be81eae 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt @@ -67,7 +67,7 @@ class MessageSvc { latestRambleNumber = 20, otherRambleNumber = 3, onlineSyncFlag = 1, - serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY, + // serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY, syncCookie = client.c2cMessageSync.syncCookie, syncFlag = client.c2cMessageSync.syncFlag, msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt index f31c6329b..796450b86 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt @@ -11,9 +11,12 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.* import net.mamoe.mirai.qqandroid.utils.GuidSource import net.mamoe.mirai.qqandroid.utils.MacOrAndroidIdChangeFlag import net.mamoe.mirai.qqandroid.utils.guidFlag -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.MiraiDebugAPI +import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.decryptBy +import net.mamoe.mirai.utils.currentTimeMillis +import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.discardExact @@ -242,11 +245,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt sealed class LoginPacketResponse : Packet { - object Success : LoginPacketResponse(){ + object Success : LoginPacketResponse() { override fun toString(): String { return "LoginPacketResponse.Success" } } + data class Error( val title: String, val message: String, @@ -258,7 +262,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt class Slider( val data: IoBuffer, val sign: ByteArray - ) : Captcha(){ + ) : Captcha() { override fun toString(): String { return "LoginPacketResponse.Captcha.Slider" } @@ -267,7 +271,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt class Picture( val data: IoBuffer, val sign: ByteArray - ) : Captcha(){ + ) : Captcha() { override fun toString(): String { return "LoginPacketResponse.Captcha.Picture" } @@ -292,18 +296,19 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt val subCommand = readUShort().toInt() println("subCommand=$subCommand") - val type = readByte() + val type = readUByte() println("type=$type") discardExact(2) val tlvMap: TlvMap = this.readTLVMap() + tlvMap.printTLVMap() return when (type.toInt()) { 0 -> onLoginSuccess(tlvMap, bot) 1, 15 -> onErrorMessage(tlvMap) 2 -> onSolveLoginCaptcha(tlvMap, bot) - -96 -> onUnsafeDeviceLogin(tlvMap) - -52 /*0xCC=204*/ -> onSMSVerifyNeeded(tlvMap, bot) - else -> error("unknown login result type: $type") + 160 /*-96*/ -> onUnsafeDeviceLogin(tlvMap) + 204 /*-52*/ -> onSMSVerifyNeeded(tlvMap, bot) + else -> tlvMap[0x149]?.let { bot.client.analysisTlv149(it) } ?: error("unknown login result type: $type") } } @@ -336,7 +341,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt @InternalAPI @UseExperimental(MiraiDebugAPI::class) - private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse. Captcha { + private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Captcha { // val ret = tlvMap[0x104]?.let { println(it.toUHexString()) } println() val question = tlvMap[0x165] ?: error("CAPTCHA QUESTION UNKNOWN") @@ -380,7 +385,6 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt DebugLogger.warning(bytes.encodeToString()) } - tlvMap119[0x149]?.let { client.analysisTlv149(it) } tlvMap119[0x130]?.let { client.analysisTlv130(it) } tlvMap119[0x113]?.let { client.analysisTlv113(it) } @@ -677,22 +681,16 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt /** * 错误消息 */ - private fun QQAndroidClient.analysisTlv149(t149: ByteArray) { - data class ErrorMessage( - val type: Short, - val title: String, - val content: String, - val otherInfo: String - ) + private fun QQAndroidClient.analysisTlv149(t149: ByteArray): LoginPacketResponse.Error { - t149.read { + return t149.read { val type: Short = readShort() val title: String = readUShortLVString() val content: String = readUShortLVString() val otherInfo: String = readUShortLVString() // do not write class into read{} block. CompilationException!! - error("Got error message: " + ErrorMessage(type, title, content, otherInfo)) // nice toString + LoginPacketResponse.Error(title = title, message = content, errorInfo = otherInfo) // nice toString } } diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt index ed5d20b86..4bdaff37a 100644 --- a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt @@ -4,7 +4,10 @@ package androidPacketTests import kotlinx.io.core.* import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger -import net.mamoe.mirai.utils.cryptor.* +import net.mamoe.mirai.utils.cryptor.ECDH +import net.mamoe.mirai.utils.cryptor.contentToString +import net.mamoe.mirai.utils.cryptor.decryptBy +import net.mamoe.mirai.utils.cryptor.initialPublicKey import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.discardExact import net.mamoe.mirai.utils.md5 @@ -205,7 +208,7 @@ fun ByteReadPacket.analysisOneFullPacket(): ByteReadPacket = debugIfFail("Failed ECDH.calculateShareKey( loadPrivateKey(ecdhPrivateKeyS), //"04cb366698561e936e80c157e074cab13b0bb68ddeb2824548a1b18dd4fb6122afe12fe48c5266d8d7269d7651a8eb6fe7".chunkedHexToBytes().adjustToPublicKey() // QQ: 04cb366698561e936e80c157e074cab13b0bb68ddeb2824548a1b18dd4fb6122afe12fe48c5266d8d7269d7651a8eb6fe7 - publicKey.adjustToPublicKey() + ECDH.constructPublicKey("30 46 30 10 06 07 2A 86 48 CE 3D 02 01 06 05 2B 81 04 00 1F 03 32 00".hexToBytes() + publicKey) ) } @@ -237,7 +240,9 @@ fun ByteReadPacket.analysisOneFullPacket(): ByteReadPacket = debugIfFail("Failed DebugLogger.info("发送 login!! 正在获取 tgtgtKey") try { discardExact(4) - readTLVMap()[0x106] + val tlvMap = readTLVMap() + tlvMap.printTLVMap() + tlvMap[0x106] ?.also { DebugLogger.info("找到了 0x106") } ?.decryptBy(md5(passwordMd5 + ByteArray(4) + uin.toInt().toByteArray())) ?.read { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt index cb343327a..e93a21355 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt @@ -66,13 +66,7 @@ private const val constantHead = "3046301006072A8648CE3D020106052B8104001F033200 private val byteArray_04 = byteArrayOf(0x04) fun ByteArray.adjustToPublicKey(): ECDHPublicKey { - val key = if (this[0].toInt() == 0x02) { // from server - commonHeadFor02 + this - } else if (!this.toUHexString("").startsWith(constantHead)) { - commonHeadForNot02 + - if (this[0].toInt() == 0x04 || this[0].toInt() == 0x03) this - else (byteArray_04 + this) - } else this + val head = if(this.size<30) "302E301006072A8648CE3D020106052B8104001F031A00" else "3046301006072A8648CE3D020106052B8104001F03320004" - return ECDH.constructPublicKey(key) + return ECDH.constructPublicKey((head + this.toUHexString("")).chunkedHexToBytes()) } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt index 2c598eead..3bd8002ae 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt @@ -186,9 +186,9 @@ fun Input.readFlatTUVarIntMap(expectingEOF: Boolean = false, tagSize: Int = 1): fun Map<Int, ByteArray>.printTLVMap(name: String = "", keyLength: Int = 2) = debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() }.mapKeys { when (keyLength) { - 1 -> it.key.toUByte().toUHexString() - 2 -> it.key.toUShort().toUHexString() - 4 -> it.key.toUInt().toUHexString() + 1 -> it.key.toUByte().contentToString() + 2 -> it.key.toUShort().contentToString() + 4 -> it.key.toUInt().contentToString() else -> illegalArgument("Expecting 1, 2 or 4 for keyLength") } }.entries.joinToString(prefix = "{", postfix = "}", separator = "\n"))