mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-26 07:20:09 +08:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt
This commit is contained in:
commit
7bc63b7e9a
mirai-core-qqandroid/src
commonMain/kotlin/net/mamoe/mirai/qqandroid/network
jvmTest/kotlin/androidPacketTests
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils
@ -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
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
}
|
@ -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"))
|
||||
|
Loading…
Reference in New Issue
Block a user