LoginPacket done.

This commit is contained in:
Him188 2020-01-07 20:08:51 +08:00
parent 78ee01ded1
commit 809cfcb299
4 changed files with 59 additions and 26 deletions

View File

@ -54,12 +54,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
launch(CoroutineName("Incoming Packet handler")) {
rawInput.debugPrint("Received").use {
if (it.remaining == 0L) {
rawInput.debugPrint("Received").use { input ->
if (input.remaining == 0L) {
bot.logger.error("Empty packet received. Consider if bad packet was sent.")
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) {
return@parseIncomingPacket
}

View File

@ -49,6 +49,8 @@ internal open class QQAndroidClient(
val apkVersionName: ByteArray = "8.2.0".toByteArray()
var loginState = 0
val appClientVersion: Int = 0
var networkType: NetworkType = NetworkType.WIFI

View File

@ -257,16 +257,16 @@ internal interface EncryptMethodECDH : EncryptMethod {
writeFully(ByteArray(16))
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")
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" }
})*/
})
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("26 33 BA EC 86 EB 79 E6 BC E0 20 06 5E A9 56 6C".hexToBytes(), body)
encryptAndWrite(ecdh.keyPair.shareKey, body)
}
}

View File

@ -4,8 +4,10 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer
import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.data.Packet
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.commandName
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
@ -16,6 +18,7 @@ import net.mamoe.mirai.utils.cryptor.decryptBy
import net.mamoe.mirai.utils.io.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.jvm.JvmName
/**
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
@ -41,11 +44,20 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
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)
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 }
@ -61,9 +73,6 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
when (val flag1 = readInt()) {
0x0A -> when (val flag2 = readByte().toInt()) {
0x02 -> {
val extraData = readIoBuffer(readInt() - 4).debugCopyUse {
this.debugPrint("Extra data")
}
val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" }
@ -90,33 +99,55 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
commandName = readString(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)
}
bot.logger.verbose(commandName)
val packetFactory = findPacketFactory(commandName)
val qq: Long
val subCommandId: Int
readIoBuffer(readInt() - 4).withUse {
check(readByte().toInt() == 2)
discardExact(2) // 27 + 2 + body.size
discardExact(2) // const, =8001
readShort() // commandId
readShort() // innerSequenceId
qq = readInt().toLong()
this.discardExact(2) // 27 + 2 + body.size
this.discardExact(2) // const, =8001
this.readShort() // commandId
this.readShort() // const, =0x0001
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
packetFactory.run {
bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey()).read {
decode(bot)
}
}
var data = this.decryptBy(bot.client.ecdh.keyPair.shareKey, this.readRemaining - 1)
val peerShareKey = bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
data = data.decryptBy(peerShareKey)
packetFactory.decode(bot, data.toReadPacket())
}
else -> error("Illegal encryption method. expected 4, got $encryptionMethod")
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 0 or 4, got $encryptionMethod")
}
consumer(packet, packetFactory.id, ssoSequenceId)