Commit 809cfcb2 authored by Him188's avatar Him188

LoginPacket done.

parent 78ee01de
...@@ -54,12 +54,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -54,12 +54,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
launch(CoroutineName("Incoming Packet handler")) { launch(CoroutineName("Incoming Packet handler")) {
rawInput.debugPrint("Received").use { rawInput.debugPrint("Received").use { input ->
if (it.remaining == 0L) { if (input.remaining == 0L) {
bot.logger.error("Empty packet received. Consider if bad packet was sent.") bot.logger.error("Empty packet received. Consider if bad packet was sent.")
return@launch return@launch
} }
KnownPacketFactories.parseIncomingPacket(bot, rawInput) { packet: Packet, packetId: PacketId, sequenceId: Int -> KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int ->
if (PacketReceivedEvent(packet).broadcast().cancelled) { if (PacketReceivedEvent(packet).broadcast().cancelled) {
return@parseIncomingPacket return@parseIncomingPacket
} }
......
...@@ -49,6 +49,8 @@ internal open class QQAndroidClient( ...@@ -49,6 +49,8 @@ internal open class QQAndroidClient(
val apkVersionName: ByteArray = "8.2.0".toByteArray() val apkVersionName: ByteArray = "8.2.0".toByteArray()
var loginState = 0
val appClientVersion: Int = 0 val appClientVersion: Int = 0
var networkType: NetworkType = NetworkType.WIFI var networkType: NetworkType = NetworkType.WIFI
......
...@@ -257,16 +257,16 @@ internal interface EncryptMethodECDH : EncryptMethod { ...@@ -257,16 +257,16 @@ internal interface EncryptMethodECDH : EncryptMethod {
writeFully(ByteArray(16)) writeFully(ByteArray(16))
writeShort(258) // const writeShort(258) // const
writeShortLVByteArray("04 CB 36 66 98 56 1E 93 6E 80 C1 57 E0 74 CA B1 3B 0B B6 8D DE B2 82 45 48 A1 B1 8D D4 FB 61 22 AF E1 2F E4 8C 52 66 D8 D7 26 9D 76 51 A8 EB 6F E7".hexToBytes()) // writeShortLVByteArray("04 CB 36 66 98 56 1E 93 6E 80 C1 57 E0 74 CA B1 3B 0B B6 8D DE B2 82 45 48 A1 B1 8D D4 FB 61 22 AF E1 2F E4 8C 52 66 D8 D7 26 9D 76 51 A8 EB 6F E7".hexToBytes())
/*writeShortLVByteArray(ecdh.keyPair.publicKey.getEncoded().drop(23).take(49).toByteArray().also { writeShortLVByteArray(ecdh.keyPair.publicKey.getEncoded().drop(23).take(49).toByteArray().also {
it.toUHexString().debugPrint("PUBLIC KEY") it.toUHexString().debugPrint("PUBLIC KEY")
check(it[0].toInt() == 0x04) { "Bad publicKey generated. Expected first element=0x04, got${it[0]}" } check(it[0].toInt() == 0x04) { "Bad publicKey generated. Expected first element=0x04, got${it[0]}" }
//check(ecdh.calculateShareKeyByPeerPublicKey(it.adjustToPublicKey()).contentEquals(ecdh.keyPair.shareKey)) { "PublicKey Validation failed" } //check(ecdh.calculateShareKeyByPeerPublicKey(it.adjustToPublicKey()).contentEquals(ecdh.keyPair.shareKey)) { "PublicKey Validation failed" }
})*/ })
encryptAndWrite("26 33 BA EC 86 EB 79 E6 BC E0 20 06 5E A9 56 6C".hexToBytes(), body) // encryptAndWrite("26 33 BA EC 86 EB 79 E6 BC E0 20 06 5E A9 56 6C".hexToBytes(), body)
//encryptAndWrite(ecdh.keyPair.shareKey, body) encryptAndWrite(ecdh.keyPair.shareKey, body)
} }
} }
......
...@@ -4,8 +4,10 @@ import kotlinx.io.core.ByteReadPacket ...@@ -4,8 +4,10 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId.commandName import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId.commandName
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
...@@ -16,6 +18,7 @@ import net.mamoe.mirai.utils.cryptor.decryptBy ...@@ -16,6 +18,7 @@ import net.mamoe.mirai.utils.cryptor.decryptBy
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.jvm.JvmName
/** /**
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包 * 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
...@@ -41,11 +44,20 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt ...@@ -41,11 +44,20 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
abstract suspend fun ByteReadPacket.decode(bot: QQAndroidBot): TPacket abstract suspend fun ByteReadPacket.decode(bot: QQAndroidBot): TPacket
} }
@JvmName("decode0")
private suspend inline fun <P : Packet> PacketFactory<P, *>.decode(bot: QQAndroidBot, packet: ByteReadPacket): P {
return this.run {
packet.decode(bot)
}
}
private val DECRYPTER_16_ZERO = ByteArray(16) private val DECRYPTER_16_ZERO = ByteArray(16)
internal typealias PacketConsumer = suspend (packet: Packet, packetId: PacketId, ssoSequenceId: Int) -> Unit internal typealias PacketConsumer = suspend (packet: Packet, packetId: PacketId, ssoSequenceId: Int) -> Unit
internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListOf() { internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListOf(
LoginPacket
) {
fun findPacketFactory(commandName: String): PacketFactory<*, *> = this.first { it.id.commandName == commandName } fun findPacketFactory(commandName: String): PacketFactory<*, *> = this.first { it.id.commandName == commandName }
...@@ -61,9 +73,6 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO ...@@ -61,9 +73,6 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
when (val flag1 = readInt()) { when (val flag1 = readInt()) {
0x0A -> when (val flag2 = readByte().toInt()) { 0x0A -> when (val flag2 = readByte().toInt()) {
0x02 -> { 0x02 -> {
val extraData = readIoBuffer(readInt() - 4).debugCopyUse {
this.debugPrint("Extra data")
}
val flag3 = readByte().toInt() val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" } check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" }
...@@ -90,33 +99,55 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO ...@@ -90,33 +99,55 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
commandName = readString(readInt() - 4) commandName = readString(readInt() - 4)
val unknown = readBytes(readInt() - 4) val unknown = readBytes(readInt() - 4)
if (unknown.toInt() != 0x02B05B8B) DebugLogger.debug("got new unknown: $unknown") if (unknown.toInt() != 0x02B05B8B) DebugLogger.debug("got new unknown: ${unknown.toUHexString()}")
check(readInt() == 0) check(readInt() == 0)
} }
bot.logger.verbose(commandName)
val packetFactory = findPacketFactory(commandName) val packetFactory = findPacketFactory(commandName)
val qq: Long val qq: Long
val subCommandId: Int val subCommandId: Int
readIoBuffer(readInt() - 4).withUse { readIoBuffer(readInt() - 4).withUse {
check(readByte().toInt() == 2) check(readByte().toInt() == 2)
discardExact(2) // 27 + 2 + body.size this.discardExact(2) // 27 + 2 + body.size
discardExact(2) // const, =8001 this.discardExact(2) // const, =8001
readShort() // commandId this.readShort() // commandId
readShort() // innerSequenceId this.readShort() // const, =0x0001
qq = readInt().toLong() qq = this.readInt().toLong()
val encryptionMethod = this.readShort().toInt()
discardExact(1) // const = 0
val packet = when (val encryptionMethod = readByte().toInt()) { this.discardExact(1) // const = 0
val packet = when (encryptionMethod) {
4 -> { // peer public key, ECDH 4 -> { // peer public key, ECDH
packetFactory.run { var data = this.decryptBy(bot.client.ecdh.keyPair.shareKey, this.readRemaining - 1)
bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey()).read {
decode(bot) val peerShareKey = bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
data = data.decryptBy(peerShareKey)
packetFactory.decode(bot, data.toReadPacket())
}
0 -> {
val data = if (bot.client.loginState == 0) {
ByteArrayPool.useInstance { byteArrayBuffer ->
val size = this.readRemaining - 1
this.readFully(byteArrayBuffer, 0, size)
runCatching {
byteArrayBuffer.decryptBy(bot.client.ecdh.keyPair.shareKey, size)
}.getOrElse {
byteArrayBuffer.decryptBy(bot.client.tgtgtKey, size)
} // 这里实际上应该用 privateKey(另一个random出来的key)
} }
} else {
this.decryptBy(bot.client.tgtgtKey, 0, this.readRemaining - 1)
} }
packetFactory.decode(bot, data.toReadPacket())
} }
else -> error("Illegal encryption method. expected 4, got $encryptionMethod") else -> error("Illegal encryption method. expected 0 or 4, got $encryptionMethod")
} }
consumer(packet, packetFactory.id, ssoSequenceId) consumer(packet, packetFactory.id, ssoSequenceId)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment