This commit is contained in:
Him188 2020-01-29 20:30:20 +08:00
parent 1cd1a19dbe
commit ac52cbb47e
5 changed files with 28 additions and 132 deletions

View File

@ -1,82 +0,0 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.Cmd0x352Packet
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
internal object GetMsgRequest : PacketFactory<MsgSvc.PbGetMsgResp>("MessageSvc.PbGetMsg") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): MsgSvc.PbGetMsgResp {
println("received MsgSvc.PbGetMsgResp")
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
/**
@Serializable
class PbGetMsgReq(
@SerialId(1) val syncFlag: Int /* enum */ = 0,
@SerialId(2) val syncCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val rambleFlag: Int = 1,
@SerialId(4) val latestRambleNumber: Int = 20,
@SerialId(5) val otherRambleNumber: Int = 3,
@SerialId(6) val onlineSyncFlag: Int = 1,
@SerialId(7) val contextFlag: Int = 0,
@SerialId(8) val whisperSessionId: Int = 0,
@SerialId(9) val msgReqType: Int = 0,
@SerialId(10) val pubaccountCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val serverBuf: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class RequestPushNotify(
@SerialId(0) val uin: Long = 0L,
@SerialId(1) val ctype: Byte = 0,
@SerialId(2) val strService: String?,
@SerialId(3) val strCmd: String?,
@SerialId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(5) val usMsgType: Int?,
@SerialId(6) val wUserActive: Int?,
@SerialId(7) val wGeneralFlag: Int?,
@SerialId(8) val bindedUin: Long?,
@SerialId(9) val stMsgInfo: MsgInfo?,
@SerialId(10) val msgCtrlBuf: String?,
@SerialId(11) val serverBuf: ByteArray?,
@SerialId(12) val pingFlag: Long?,
@SerialId(13) val svrip: Int?
) : JceStruct, Packet
*/
operator fun invoke(
client: QQAndroidClient,
notify: RequestPushNotify
): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.d2Key) {
val req = MsgSvc.PbGetMsgReq(
serverBuf = notify.serverBuf ?: EMPTY_BYTE_ARRAY,
msgReqType = notify.usMsgType ?: 0,
syncFlag = 0,
rambleFlag = 0,
contextFlag = 1,
latestRambleNumber = 20,
otherRambleNumber = 3,
onlineSyncFlag = 1
)
val data = ProtoBuf.dump(
MsgSvc.PbGetMsgReq.serializer(),
req
)
writeInt(data.size)
writeFully(data, 0, data.size)
}
}

View File

@ -25,6 +25,9 @@ import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.toReadPacket
class MessageSvc {
/**
* 告知要刷新消息
*/
internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify {
discardExact(8)
@ -42,13 +45,18 @@ class MessageSvc {
}
}
/**
* 进行刷新消息
*/
internal object PbGetMsg : PacketFactory<MultiPacket<FriendMessage>>("MessageSvc.PbGetMsg") {
val EXTRA_DATA = "08 00 12 33 6D 6F 64 65 6C 3A 78 69 61 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes()
operator fun invoke(
client: QQAndroidClient,
from: RequestPushNotify
): OutgoingPacket = buildOutgoingUniPacket(
client,
extraData = "08 00 12 33 6D 6F 64 65 6C 3A 78 69 61 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes().toReadPacket()
extraData = EXTRA_DATA.toReadPacket()
) {
writeProtoBuf(
MsgSvc.PbGetMsgReq.serializer(),

View File

@ -14,7 +14,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush
import net.mamoe.mirai.qqandroid.utils.toMessageChain
internal class OnlinePush {
/**
* 接受群消息
*/
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
@UseExperimental(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {

View File

@ -274,12 +274,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
println("type=$type")
discardExact(2)
val tlvMap: Map<Int, ByteArray> = this.readTLVMap()
val tlvMap: TlvMap = this.readTLVMap()
return when (type.toInt()) {
0 -> onLoginSuccess(tlvMap, bot)
1, 15 -> onErrorMessage(tlvMap)
2 -> onSolveLoginCaptcha(tlvMap, bot)
-96 -> onUnsafeDeviceLogin(tlvMap, bot)
-96 -> onUnsafeDeviceLogin(tlvMap)
-52 -> onSMSVerifyNeeded(tlvMap, bot)
else -> error("unknown login result type: $type")
}
@ -287,18 +287,18 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
private fun onSMSVerifyNeeded(
tlvMap: Map<Int, ByteArray>,
tlvMap: TlvMap,
bot: QQAndroidBot
): LoginPacketResponse.SMSVerifyCodeNeeded {
bot.client.t104 = tlvMap[0x104]!!
return LoginPacketResponse.SMSVerifyCodeNeeded(tlvMap[0x174] ?: EMPTY_BYTE_ARRAY, tlvMap[0x402]!!)
bot.client.t104 = tlvMap.getOrFail(0x104)
return LoginPacketResponse.SMSVerifyCodeNeeded(tlvMap[0x174] ?: EMPTY_BYTE_ARRAY, tlvMap.getOrFail(0x402))
}
private fun onUnsafeDeviceLogin(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse.UnsafeLogin {
return LoginPacketResponse.UnsafeLogin(tlvMap[0x204]!!.toReadPacket().readRemainingBytes().encodeToString())
private fun onUnsafeDeviceLogin(tlvMap: TlvMap): LoginPacketResponse.UnsafeLogin {
return LoginPacketResponse.UnsafeLogin(tlvMap.getOrFail(0x204).toReadPacket().readRemainingBytes().encodeToString())
}
private fun onErrorMessage(tlvMap: Map<Int, ByteArray>): LoginPacketResponse.Error {
private fun onErrorMessage(tlvMap: TlvMap): LoginPacketResponse.Error {
return tlvMap[0x146]?.toReadPacket()?.run {
readShort() // ver
readShort() // code
@ -313,8 +313,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
@InternalAPI
@UseExperimental(MiraiDebugAPI::class)
private fun onSolveLoginCaptcha(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse. Captcha {
val client = bot.client
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")
@ -322,8 +321,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
0x36 -> {
//图片验证
DebugLogger.debug("是一个图片验证码")
bot.client.t104 = tlvMap[0x104]!!
val imageData = tlvMap[0x105]!!.toReadPacket()
bot.client.t104 = tlvMap.getOrFail(0x104)
val imageData = tlvMap.getOrFail(0x105).toReadPacket()
val signInfoLength = imageData.readShort()
imageData.discardExact(2)//image Length
val sign = imageData.readBytes(signInfoLength.toInt())
@ -332,15 +331,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
sign = sign
)
}
else -> {
error("UNKNOWN CAPTCHA QUESTION: $question")
}
else -> error("UNKNOWN CAPTCHA QUESTION: $question")
}
return TODO()
}
@UseExperimental(MiraiDebugAPI::class)
private fun onLoginSuccess(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse.Success {
private fun onLoginSuccess(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Success {
val client = bot.client
println("TLV KEYS: " + tlvMap.keys.joinToString { it.contentToString() })
@ -544,7 +540,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
}
private fun Map<Int, ByteArray>.getOrEmpty(key: Int): ByteArray {
private fun TlvMap.getOrEmpty(key: Int): ByteArray {
return this[key] ?: byteArrayOf()
}
@ -623,7 +619,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
* 设置 [QQAndroidClient.uin]
*/
private fun QQAndroidClient.analysisTlv113(t113: ByteArray) = t113.read {
val uin = readUInt().toLong()
_uin = readUInt().toLong()
/*
// nothing to do

View File

@ -68,38 +68,22 @@ private fun processFullPacketWithoutLength(packet: ByteReadPacket) {
val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" }
<<<<<<< Updated upstream
val uinAccount = readString(readInt() - 4)//uin
=======
println("uinAccount=" + readString(readInt() - 4))//uin
>>>>>>> Stashed changes
//debugPrint("remaining")
(if (flag2 == 2) {
<<<<<<< Updated upstream
//PacketLogger.verbose("SSO, 尝试使用 16 zero 解密.")
=======
PacketLogger.verbose("SSO, 尝试使用 16 zero 解密.")
>>>>>>> Stashed changes
kotlin.runCatching {
decryptBy(DECRYPTER_16_ZERO).also { PacketLogger.verbose("成功使用 16 zero 解密") }
}
} else {
<<<<<<< Updated upstream
//PacketLogger.verbose("Uni, 尝试使用 d2Key 解密.")
=======
PacketLogger.verbose("Uni, 尝试使用 d2Key 解密.")
>>>>>>> Stashed changes
kotlin.runCatching {
decryptBy(D2Key).also { PacketLogger.verbose("成功使用 d2Key 解密") }
}
}).getOrElse {
<<<<<<< Updated upstream
PacketLogger.verbose("解密失败, 尝试其他各种key")
=======
PacketLogger.verbose("失败, 尝试其他各种key")
>>>>>>> Stashed changes
this.readBytes().tryDecryptOrNull()?.toReadPacket()
}?.debugPrint("sso/uni body=")?.let {
if (flag1 == 0x0A) {
@ -111,11 +95,7 @@ private fun processFullPacketWithoutLength(packet: ByteReadPacket) {
val bytes = it.data.readBytes()
if (flag2 == 2 && it.packetFactory != null) {
PacketLogger.debug("Oicq Reuqest= " + bytes.toUHexString())
<<<<<<< Updated upstream
try {
=======
try{
>>>>>>> Stashed changes
bytes.toReadPacket().parseOicqResponse {
if (it.packetFactory.commandName == "wtlogin.login") {
DebugLogger.info("服务器发来了 wtlogin.login. 正在解析 key")
@ -149,11 +129,7 @@ private fun processFullPacketWithoutLength(packet: ByteReadPacket) {
}
}
}
<<<<<<< Updated upstream
} catch (e: Exception) {
=======
}catch (e: Exception){
>>>>>>> Stashed changes
e.printStackTrace()
}
} else // always discarded. 00 1C
@ -189,15 +165,9 @@ private fun ByteReadPacket.parseOicqResponse(body: ByteReadPacket.() -> Unit) {
val packet = when (encryptionMethod) {
4 -> { // peer public key, ECDH
var data = this.decryptBy(shareKeyCalculatedByConstPubKey, 0, this.readRemaining - 1)
<<<<<<< Updated upstream
data.read {
println("第一层解密: ${data.toUHexString()}")
val peerShareKey = ECDH.calculateShareKey(loadPrivateKey(ecdhPrivateKeyS), readUShortLVByteArray().adjustToPublicKey())
=======
data.read{
println("第一层解密: ${data.toUHexString()}")
val peerShareKey = ECDH.calculateShareKey(loadPrivateKey(ecdhPrivateKeyS), readUShortLVByteArray().adjustToPublicKey())
>>>>>>> Stashed changes
body(this.decryptBy(peerShareKey))
}
}