mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-19 15:34:42 +08:00
[core] Handle rare case on packet pipeline (#2450)
* Handle rare case on packet pipeline Fix #2449, should help #1603 * Fix and improve tips and improve the readability of code * Improve wording of tips Co-authored-by: Him188 <Him188@mamoe.net> * Change d2Key error type to PROTOCOL_UPDATED * Reformat code --------- Co-authored-by: Him188 <Him188@mamoe.net>
This commit is contained in:
parent
403380514a
commit
28b1032acd
@ -123,7 +123,15 @@ internal class PacketCodecImpl : PacketCodec {
|
|||||||
val raw = try {
|
val raw = try {
|
||||||
when (encryptMethod) {
|
when (encryptMethod) {
|
||||||
2 -> TEA.decrypt(buffer, DECRYPTER_16_ZERO, size)
|
2 -> TEA.decrypt(buffer, DECRYPTER_16_ZERO, size)
|
||||||
1 -> TEA.decrypt(buffer, client.wLoginSigInfo.d2Key, size)
|
1 -> {
|
||||||
|
TEA.decrypt(buffer, kotlin.runCatching { client.wLoginSigInfo.d2Key }.getOrElse {
|
||||||
|
throw PacketCodecException(
|
||||||
|
"Received packet needed d2Key to decrypt but d2Key doesn't existed, ignoring. Please report to https://github.com/mamoe/mirai/issues/new/choose if you see anything abnormal",
|
||||||
|
PROTOCOL_UPDATED
|
||||||
|
)
|
||||||
|
}, size)
|
||||||
|
}
|
||||||
|
|
||||||
0 -> buffer
|
0 -> buffer
|
||||||
else -> throw PacketCodecException("Unknown encrypt type=$encryptMethod", PROTOCOL_UPDATED)
|
else -> throw PacketCodecException("Unknown encrypt type=$encryptMethod", PROTOCOL_UPDATED)
|
||||||
}.let { decryptedData ->
|
}.let { decryptedData ->
|
||||||
@ -163,7 +171,7 @@ internal class PacketCodecImpl : PacketCodec {
|
|||||||
raw.sequenceId,
|
raw.sequenceId,
|
||||||
raw.body.withUse {
|
raw.body.withUse {
|
||||||
try {
|
try {
|
||||||
parseOicqResponse(client)
|
parseOicqResponse(client, raw.commandName)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
throw PacketCodecException(e, PacketCodecException.Kind.OTHER)
|
throw PacketCodecException(e, PacketCodecException.Kind.OTHER)
|
||||||
}
|
}
|
||||||
@ -268,10 +276,76 @@ internal class PacketCodecImpl : PacketCodec {
|
|||||||
|
|
||||||
private fun ByteReadPacket.parseOicqResponse(
|
private fun ByteReadPacket.parseOicqResponse(
|
||||||
client: SsoSession,
|
client: SsoSession,
|
||||||
|
commandName: String
|
||||||
): ByteArray {
|
): ByteArray {
|
||||||
readByte().toInt().let {
|
val qqEcdh = (client as QQAndroidClient).bot.components[EcdhInitialPublicKeyUpdater].getQQEcdh()
|
||||||
check(it == 2) { "$it" }
|
fun decrypt(encryptionMethod: Int): ByteArray {
|
||||||
|
return when (encryptionMethod) {
|
||||||
|
4 -> {
|
||||||
|
val size = (this.remaining - 1).toInt()
|
||||||
|
val data =
|
||||||
|
TEA.decrypt(
|
||||||
|
this.readBytes(),
|
||||||
|
qqEcdh.initialQQShareKey,
|
||||||
|
length = size
|
||||||
|
)
|
||||||
|
|
||||||
|
val peerShareKey =
|
||||||
|
qqEcdh.calculateQQShareKey(Ecdh.Instance.importPublicKey(readUShortLVByteArray()))
|
||||||
|
TEA.decrypt(data, peerShareKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
3 -> {
|
||||||
|
val size = (this.remaining - 1).toInt()
|
||||||
|
// session
|
||||||
|
TEA.decrypt(
|
||||||
|
this.readBytes(),
|
||||||
|
client.wLoginSigInfo.wtSessionTicketKey,
|
||||||
|
length = size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
0 -> {
|
||||||
|
if (client.loginState == 0) {
|
||||||
|
val size = (this.remaining - 1).toInt()
|
||||||
|
val byteArrayBuffer = this.readBytes(size)
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
TEA.decrypt(byteArrayBuffer, qqEcdh.initialQQShareKey, length = size)
|
||||||
|
}.getOrElse {
|
||||||
|
TEA.decrypt(byteArrayBuffer, client.randomKey, length = size)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val size = (this.remaining - 1).toInt()
|
||||||
|
TEA.decrypt(this.readBytes(), client.randomKey, length = size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("Illegal encryption method. expected 0 or 4, got $encryptionMethod")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val packetType = readByte().toInt()
|
||||||
|
if (packetType != 2) {
|
||||||
|
val fullPacketDump = copy().readBytes().toUHexString()
|
||||||
|
var decryptedData: String? = null
|
||||||
|
if (remaining > 15) {
|
||||||
|
discardExact(12)
|
||||||
|
val encryptionMethod = this.readUShort().toInt()
|
||||||
|
discardExact(1)
|
||||||
|
decryptedData = kotlin.runCatching {
|
||||||
|
decrypt(encryptionMethod).toUHexString()
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
throw PacketCodecException(
|
||||||
|
"Received unknown oicq packet type = $packetType, command name = $commandName, ignoring..." +
|
||||||
|
"\nPlease report this message to https://github.com/mamoe/mirai/issues/new/choose, \n" +
|
||||||
|
"Full packet dump: $fullPacketDump\n" +
|
||||||
|
"Decrypted data (contains your encrypted password, please change your password after reporting issue): $decryptedData",
|
||||||
|
PROTOCOL_UPDATED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
this.discardExact(2)
|
this.discardExact(2)
|
||||||
this.discardExact(2)
|
this.discardExact(2)
|
||||||
this.readUShort()
|
this.readUShort()
|
||||||
@ -280,51 +354,7 @@ internal class PacketCodecImpl : PacketCodec {
|
|||||||
val encryptionMethod = this.readUShort().toInt()
|
val encryptionMethod = this.readUShort().toInt()
|
||||||
|
|
||||||
this.discardExact(1)
|
this.discardExact(1)
|
||||||
val qqEcdh =
|
return decrypt(encryptionMethod)
|
||||||
(client as QQAndroidClient).bot.components[EcdhInitialPublicKeyUpdater].getQQEcdh()
|
|
||||||
return when (encryptionMethod) {
|
|
||||||
4 -> {
|
|
||||||
val size = (this.remaining - 1).toInt()
|
|
||||||
val data =
|
|
||||||
TEA.decrypt(
|
|
||||||
this.readBytes(),
|
|
||||||
qqEcdh.initialQQShareKey,
|
|
||||||
length = size
|
|
||||||
)
|
|
||||||
|
|
||||||
val peerShareKey =
|
|
||||||
qqEcdh.calculateQQShareKey(Ecdh.Instance.importPublicKey(readUShortLVByteArray()))
|
|
||||||
TEA.decrypt(data, peerShareKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
3 -> {
|
|
||||||
val size = (this.remaining - 1).toInt()
|
|
||||||
// session
|
|
||||||
TEA.decrypt(
|
|
||||||
this.readBytes(),
|
|
||||||
client.wLoginSigInfo.wtSessionTicketKey,
|
|
||||||
length = size
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
0 -> {
|
|
||||||
if (client.loginState == 0) {
|
|
||||||
val size = (this.remaining - 1).toInt()
|
|
||||||
val byteArrayBuffer = this.readBytes(size)
|
|
||||||
|
|
||||||
runCatching {
|
|
||||||
TEA.decrypt(byteArrayBuffer, qqEcdh.initialQQShareKey, length = size)
|
|
||||||
}.getOrElse {
|
|
||||||
TEA.decrypt(byteArrayBuffer, client.randomKey, length = size)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val size = (this.remaining - 1).toInt()
|
|
||||||
TEA.decrypt(this.readBytes(), client.randomKey, length = size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> error("Illegal encryption method. expected 0 or 4, got $encryptionMethod")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user