Ensure that ResponsePacket will be sent

This commit is contained in:
Him188 2019-10-24 23:26:55 +08:00
parent d5bf51a357
commit ffe8339c9c
11 changed files with 34 additions and 33 deletions

View File

@ -4,7 +4,6 @@ package net.mamoe.mirai.event
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.withContext
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.event.internal.broadcastInternal
@ -59,7 +58,7 @@ interface Cancellable {
@Suppress("UNCHECKED_CAST")
@JvmOverloads
suspend fun <E : Event> E.broadcast(context: CoroutineContext = EmptyCoroutineContext): E {
return withContext(EventScope.newCoroutineContext(context)) { this@broadcast.broadcastInternal() }
return withContext(EventScope.coroutineContext + context) { this@broadcast.broadcastInternal() }
}
/**

View File

@ -164,7 +164,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
loginResult.complete(LoginResult.TIMEOUT)
}
}
sendPacket(OutgoingTouchPacket(bot.qqAccount, this.serverIp))
sendPacket(TouchPacket(bot.qqAccount, this.serverIp))
return loginResult.await()
}
@ -206,16 +206,15 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
if (packet is ServerEventPacket) {
//no need to sync acknowledgement packets
launch {
//must ensure the response packet is sent
sendPacket(packet.ResponsePacket(bot.qqAccount, sessionKey))
}
}
if (ServerPacketReceivedEvent(bot, packet).broadcast().cancelled) {
return@coroutineScope
}
//they should be called in sequence otherwise because packet is lock-free
loginHandler.onPacketReceived(packet)
this@TIMBotNetworkHandler.forEach {
it.instance.onPacketReceived(packet)

View File

@ -15,7 +15,6 @@ import net.mamoe.mirai.network.protocol.tim.packet.event.ServerEventPacket
import net.mamoe.mirai.network.protocol.tim.packet.login.RequestSKeyPacket
import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.utils.log
import kotlin.coroutines.CoroutineContext
/**
* 动作: 获取好友列表, 点赞, 踢人等.
@ -24,9 +23,6 @@ import kotlin.coroutines.CoroutineContext
* @author Him188moe
*/
class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
override val coroutineContext: CoroutineContext
get() = session.NetworkScope.coroutineContext
companion object Key : PacketHandler.Key<ActionPacketHandler>
@ -71,14 +67,14 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
private suspend fun requestSKey() = with(session) {
withContext(coroutineContext) {
withContext(NetworkScope.coroutineContext) {
socket.sendPacket(RequestSKeyPacket())
}
}
suspend fun requestAccountInfo() = with(session) {
withContext(coroutineContext) {
withContext(NetworkScope.coroutineContext) {
socket.sendPacket(RequestAccountInfoPacket(qqAccount, sessionKey))
}
}
@ -89,5 +85,3 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
private val UninitializedPacketId: UShort = 0u

View File

@ -1,6 +1,5 @@
package net.mamoe.mirai.network.protocol.tim.handler
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import kotlin.reflect.KClass
@ -10,7 +9,7 @@ import kotlin.reflect.KClass
*/
abstract class PacketHandler(
val session: BotSession
) : CoroutineScope {
) {
abstract suspend fun onPacketReceived(packet: ServerPacket)
interface Key<T : PacketHandler>

View File

@ -10,7 +10,7 @@ import kotlin.reflect.KClass
* 临时数据包处理器
* ```kotlin
* session.addHandler<ClientTouchResponsePacket>{
* toSend { OutgoingTouchPacket() }
* toSend { TouchPacket() }
* onExpect {//it: ClientTouchResponsePacket
* //do sth.
* }

View File

@ -6,6 +6,7 @@ import kotlinx.atomicfu.atomic
import kotlinx.io.core.*
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.io.writeHex
import kotlin.jvm.JvmStatic
/**
* 发给服务器的数据包. 必须有 [PacketId] 注解或 `override` [id]. 否则将会抛出 [IllegalStateException]
@ -23,6 +24,7 @@ abstract class OutgoingPacket : Packet(), Closeable {
}
companion object {
@JvmStatic
private val sequenceIdInternal = atomic(1)
internal fun atomicNextSequenceId() = sequenceIdInternal.getAndIncrement().toUShort()
}
@ -58,6 +60,7 @@ abstract class OutgoingPacket : Packet(), Closeable {
}
}
@Suppress("unused")
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)

View File

@ -50,8 +50,10 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
//管理员 子map= {5=00 00 00 03, 8=00 00 00 04, 2=65 6F 6D 38 38 31 6D 69 48, 3=02, 4=00 00 00 10}
//群成员 子map= {5=00 00 00 03, 8=00 00 00 04, 2=65 6F 6D 38 38 31 6D 69 48, 3=02}
tlv.printTLVMap("Child TLV map")
senderPermission = when (val value0x03 = tlv.getValue(0x03)[0].toUInt()) {
0x04u -> SenderPermission.OWNER
0x03u -> SenderPermission.MEMBER
0x02u -> {
if (!tlv.containsKey(0x04)) {
SenderPermission.MEMBER
@ -64,8 +66,8 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
0x01u -> SenderPermission.MEMBER
else -> {
tlv.printTLVMap("Child TLV map")
error("Could not determine member permission, unknown TLV(key=0x03,value=$value0x03;)")
//{5=00 00 00 01, 8=00 00 00 01, 1=48 69 6D 31 38 38 6D 6F 65, 3=03}
}
}

View File

@ -41,7 +41,7 @@ class RequestSKeyPacket(
//debugDiscardExact(2)
sKey = this.readString(10)//16??
DebugLogger.logPurple("SKey=$sKey")
DebugLogger.logPurple("Skey包后面${this.readRemainingBytes().toUHexString()}")
DebugLogger.logPurple("SKey 包后面${this.readRemainingBytes().toUHexString()}")
}
}
}

View File

@ -15,7 +15,7 @@ import net.mamoe.mirai.utils.toUHexString
/**
* The packet received when logging in, used to redirect server address
*
* @see OutgoingTouchRedirectionPacket
* @see RedirectionPacket
* @see SubmitPasswordPacket
*
* @author Him188moe
@ -62,7 +62,7 @@ class TouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
* @author Him188moe
*/
@PacketId(0x08_25u)
class OutgoingTouchPacket(private val bot: UInt, private val serverIp: String) : OutgoingPacket() {
class TouchPacket(private val bot: UInt, private val serverIp: String) : OutgoingPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(bot)
this.writeHex(TIMProtocol.fixVer)
@ -86,16 +86,16 @@ class OutgoingTouchPacket(private val bot: UInt, private val serverIp: String) :
* @author Him188moe
*/
@PacketId(0x08_25u)
class OutgoingTouchRedirectionPacket(private val serverIP: String, private val qq: UInt) : OutgoingPacket() {
class RedirectionPacket(private val bot: UInt, private val serverIP: String) : OutgoingPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(qq)
this.writeQQ(bot)
this.writeHex(TIMProtocol.fixVer)
this.writeHex(TIMProtocol.touchKey)//redirection key
this.encryptAndWrite(TIMProtocol.touchKey) {
this.writeHex(TIMProtocol.constantData1)
this.writeHex(TIMProtocol.constantData2)
this.writeQQ(qq)
this.writeQQ(bot)
this.writeHex("00 01 00 00 03 09 00 0C 00 01")
this.writeIP(serverIP)
this.writeHex("01 6F A1 58 22 01 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 03 00 19")

View File

@ -1,3 +1,5 @@
@file:Suppress("UNUSED_VARIABLE")
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.io.stringOfWitch
import net.mamoe.mirai.utils.io.toUHexString

View File

@ -1,5 +1,8 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_UNSIGNED_LITERALS")
import Main.localIp
import Main.qq
import Main.sessionKey
import jpcap.JpcapCaptor
import jpcap.packet.IPPacket
import jpcap.packet.UDPPacket
@ -19,13 +22,12 @@ import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.toUHexString
/**
* 抓包分析器
* 抓包分析器.
* 设置好 [sessionKey], [localIp] [qq] 后运行即可开始抓包和自动解密
*
* @author Him188moe
*/
object Main {
const val localIp = "192.168.3."
@JvmStatic
fun main(args: Array<String>) {
val devices = JpcapCaptor.getDeviceList()
@ -77,8 +79,9 @@ object Main {
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
* 7. 查看内存, `eax` 开始的 16 bytes 便是 `sessionKey`
*/
val sessionKey: ByteArray = "B7 E2 A6 3D 90 4F 4F 74 7D 55 9C 0E 91 20 40 A5".hexToBytes()
val qq: UInt = 1040400290u
val sessionKey: ByteArray = "1D 1E 71 68 B9 41 FD 5B F3 5A 3F 71 87 B5 86 CB".hexToBytes()
const val qq: UInt = 1040400290u
const val localIp = "192.168.3."
fun dataReceived(data: ByteArray) {
//println("raw = " + data.toUHexString())