mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 02:20:14 +08:00
LoginPacket done.
This commit is contained in:
parent
78ee01ded1
commit
809cfcb299
@ -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(
|
|||||||
|
|
||||||
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 {
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
|
|
||||||
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
|
this.discardExact(1) // const = 0
|
||||||
val packet = when (val encryptionMethod = readByte().toInt()) {
|
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())
|
||||||
}
|
}
|
||||||
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)
|
consumer(packet, packetFactory.id, ssoSequenceId)
|
||||||
|
Loading…
Reference in New Issue
Block a user