1
0
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:
jiahua.liu 2020-01-29 23:07:59 +08:00
commit 7bc63b7e9a
6 changed files with 32 additions and 35 deletions
mirai-core-qqandroid/src
commonMain/kotlin/net/mamoe/mirai/qqandroid/network
jvmTest/kotlin/androidPacketTests
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils

View File

@ -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
}

View File

@ -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,

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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())
}

View File

@ -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"))