mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-09 09:50:16 +08:00
Ensure that ResponsePacket will be sent
This commit is contained in:
parent
d5bf51a357
commit
ffe8339c9c
@ -4,7 +4,6 @@ package net.mamoe.mirai.event
|
|||||||
|
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.newCoroutineContext
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.mamoe.mirai.contact.Contact
|
import net.mamoe.mirai.contact.Contact
|
||||||
import net.mamoe.mirai.event.internal.broadcastInternal
|
import net.mamoe.mirai.event.internal.broadcastInternal
|
||||||
@ -59,7 +58,7 @@ interface Cancellable {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
suspend fun <E : Event> E.broadcast(context: CoroutineContext = EmptyCoroutineContext): E {
|
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() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,7 +164,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
|
|||||||
loginResult.complete(LoginResult.TIMEOUT)
|
loginResult.complete(LoginResult.TIMEOUT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendPacket(OutgoingTouchPacket(bot.qqAccount, this.serverIp))
|
sendPacket(TouchPacket(bot.qqAccount, this.serverIp))
|
||||||
|
|
||||||
return loginResult.await()
|
return loginResult.await()
|
||||||
}
|
}
|
||||||
@ -206,16 +206,15 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (packet is ServerEventPacket) {
|
if (packet is ServerEventPacket) {
|
||||||
//no need to sync acknowledgement packets
|
//must ensure the response packet is sent
|
||||||
launch {
|
|
||||||
sendPacket(packet.ResponsePacket(bot.qqAccount, sessionKey))
|
sendPacket(packet.ResponsePacket(bot.qqAccount, sessionKey))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerPacketReceivedEvent(bot, packet).broadcast().cancelled) {
|
if (ServerPacketReceivedEvent(bot, packet).broadcast().cancelled) {
|
||||||
return@coroutineScope
|
return@coroutineScope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//they should be called in sequence otherwise because packet is lock-free
|
||||||
loginHandler.onPacketReceived(packet)
|
loginHandler.onPacketReceived(packet)
|
||||||
this@TIMBotNetworkHandler.forEach {
|
this@TIMBotNetworkHandler.forEach {
|
||||||
it.instance.onPacketReceived(packet)
|
it.instance.onPacketReceived(packet)
|
||||||
|
@ -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.protocol.tim.packet.login.RequestSKeyPacket
|
||||||
import net.mamoe.mirai.network.qqAccount
|
import net.mamoe.mirai.network.qqAccount
|
||||||
import net.mamoe.mirai.utils.log
|
import net.mamoe.mirai.utils.log
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动作: 获取好友列表, 点赞, 踢人等.
|
* 动作: 获取好友列表, 点赞, 踢人等.
|
||||||
@ -24,9 +23,6 @@ import kotlin.coroutines.CoroutineContext
|
|||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
|
class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = session.NetworkScope.coroutineContext
|
|
||||||
|
|
||||||
companion object Key : PacketHandler.Key<ActionPacketHandler>
|
companion object Key : PacketHandler.Key<ActionPacketHandler>
|
||||||
|
|
||||||
|
|
||||||
@ -71,14 +67,14 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun requestSKey() = with(session) {
|
private suspend fun requestSKey() = with(session) {
|
||||||
withContext(coroutineContext) {
|
withContext(NetworkScope.coroutineContext) {
|
||||||
socket.sendPacket(RequestSKeyPacket())
|
socket.sendPacket(RequestSKeyPacket())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun requestAccountInfo() = with(session) {
|
suspend fun requestAccountInfo() = with(session) {
|
||||||
withContext(coroutineContext) {
|
withContext(NetworkScope.coroutineContext) {
|
||||||
socket.sendPacket(RequestAccountInfoPacket(qqAccount, sessionKey))
|
socket.sendPacket(RequestAccountInfoPacket(qqAccount, sessionKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,5 +85,3 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val UninitializedPacketId: UShort = 0u
|
|
@ -1,6 +1,5 @@
|
|||||||
package net.mamoe.mirai.network.protocol.tim.handler
|
package net.mamoe.mirai.network.protocol.tim.handler
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import net.mamoe.mirai.network.BotSession
|
import net.mamoe.mirai.network.BotSession
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
|
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -10,7 +9,7 @@ import kotlin.reflect.KClass
|
|||||||
*/
|
*/
|
||||||
abstract class PacketHandler(
|
abstract class PacketHandler(
|
||||||
val session: BotSession
|
val session: BotSession
|
||||||
) : CoroutineScope {
|
) {
|
||||||
abstract suspend fun onPacketReceived(packet: ServerPacket)
|
abstract suspend fun onPacketReceived(packet: ServerPacket)
|
||||||
|
|
||||||
interface Key<T : PacketHandler>
|
interface Key<T : PacketHandler>
|
||||||
|
@ -10,7 +10,7 @@ import kotlin.reflect.KClass
|
|||||||
* 临时数据包处理器
|
* 临时数据包处理器
|
||||||
* ```kotlin
|
* ```kotlin
|
||||||
* session.addHandler<ClientTouchResponsePacket>{
|
* session.addHandler<ClientTouchResponsePacket>{
|
||||||
* toSend { OutgoingTouchPacket() }
|
* toSend { TouchPacket() }
|
||||||
* onExpect {//it: ClientTouchResponsePacket
|
* onExpect {//it: ClientTouchResponsePacket
|
||||||
* //do sth.
|
* //do sth.
|
||||||
* }
|
* }
|
||||||
|
@ -6,6 +6,7 @@ import kotlinx.atomicfu.atomic
|
|||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
||||||
import net.mamoe.mirai.utils.io.writeHex
|
import net.mamoe.mirai.utils.io.writeHex
|
||||||
|
import kotlin.jvm.JvmStatic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发给服务器的数据包. 必须有 [PacketId] 注解或 `override` [id]. 否则将会抛出 [IllegalStateException]
|
* 发给服务器的数据包. 必须有 [PacketId] 注解或 `override` [id]. 否则将会抛出 [IllegalStateException]
|
||||||
@ -23,6 +24,7 @@ abstract class OutgoingPacket : Packet(), Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
private val sequenceIdInternal = atomic(1)
|
private val sequenceIdInternal = atomic(1)
|
||||||
internal fun atomicNextSequenceId() = sequenceIdInternal.getAndIncrement().toUShort()
|
internal fun atomicNextSequenceId() = sequenceIdInternal.getAndIncrement().toUShort()
|
||||||
}
|
}
|
||||||
@ -58,6 +60,7 @@ abstract class OutgoingPacket : Packet(), Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
@ -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, 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}
|
//群成员 子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()) {
|
senderPermission = when (val value0x03 = tlv.getValue(0x03)[0].toUInt()) {
|
||||||
0x04u -> SenderPermission.OWNER
|
0x04u -> SenderPermission.OWNER
|
||||||
|
0x03u -> SenderPermission.MEMBER
|
||||||
0x02u -> {
|
0x02u -> {
|
||||||
if (!tlv.containsKey(0x04)) {
|
if (!tlv.containsKey(0x04)) {
|
||||||
SenderPermission.MEMBER
|
SenderPermission.MEMBER
|
||||||
@ -64,8 +66,8 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
|
|||||||
0x01u -> SenderPermission.MEMBER
|
0x01u -> SenderPermission.MEMBER
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
tlv.printTLVMap("Child TLV map")
|
|
||||||
error("Could not determine member permission, unknown TLV(key=0x03,value=$value0x03;)")
|
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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class RequestSKeyPacket(
|
|||||||
//debugDiscardExact(2)
|
//debugDiscardExact(2)
|
||||||
sKey = this.readString(10)//16??
|
sKey = this.readString(10)//16??
|
||||||
DebugLogger.logPurple("SKey=$sKey")
|
DebugLogger.logPurple("SKey=$sKey")
|
||||||
DebugLogger.logPurple("Skey包后面${this.readRemainingBytes().toUHexString()}")
|
DebugLogger.logPurple("SKey 包后面${this.readRemainingBytes().toUHexString()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ import net.mamoe.mirai.utils.toUHexString
|
|||||||
/**
|
/**
|
||||||
* The packet received when logging in, used to redirect server address
|
* The packet received when logging in, used to redirect server address
|
||||||
*
|
*
|
||||||
* @see OutgoingTouchRedirectionPacket
|
* @see RedirectionPacket
|
||||||
* @see SubmitPasswordPacket
|
* @see SubmitPasswordPacket
|
||||||
*
|
*
|
||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
@ -62,7 +62,7 @@ class TouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
|
|||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
@PacketId(0x08_25u)
|
@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) {
|
override fun encode(builder: BytePacketBuilder) = with(builder) {
|
||||||
this.writeQQ(bot)
|
this.writeQQ(bot)
|
||||||
this.writeHex(TIMProtocol.fixVer)
|
this.writeHex(TIMProtocol.fixVer)
|
||||||
@ -86,16 +86,16 @@ class OutgoingTouchPacket(private val bot: UInt, private val serverIp: String) :
|
|||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
@PacketId(0x08_25u)
|
@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) {
|
override fun encode(builder: BytePacketBuilder) = with(builder) {
|
||||||
this.writeQQ(qq)
|
this.writeQQ(bot)
|
||||||
this.writeHex(TIMProtocol.fixVer)
|
this.writeHex(TIMProtocol.fixVer)
|
||||||
this.writeHex(TIMProtocol.touchKey)//redirection key
|
this.writeHex(TIMProtocol.touchKey)//redirection key
|
||||||
|
|
||||||
this.encryptAndWrite(TIMProtocol.touchKey) {
|
this.encryptAndWrite(TIMProtocol.touchKey) {
|
||||||
this.writeHex(TIMProtocol.constantData1)
|
this.writeHex(TIMProtocol.constantData1)
|
||||||
this.writeHex(TIMProtocol.constantData2)
|
this.writeHex(TIMProtocol.constantData2)
|
||||||
this.writeQQ(qq)
|
this.writeQQ(bot)
|
||||||
this.writeHex("00 01 00 00 03 09 00 0C 00 01")
|
this.writeHex("00 01 00 00 03 09 00 0C 00 01")
|
||||||
this.writeIP(serverIP)
|
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")
|
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")
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("UNUSED_VARIABLE")
|
||||||
|
|
||||||
import net.mamoe.mirai.utils.hexToBytes
|
import net.mamoe.mirai.utils.hexToBytes
|
||||||
import net.mamoe.mirai.utils.io.stringOfWitch
|
import net.mamoe.mirai.utils.io.stringOfWitch
|
||||||
import net.mamoe.mirai.utils.io.toUHexString
|
import net.mamoe.mirai.utils.io.toUHexString
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
@file:Suppress("EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||||
|
|
||||||
|
import Main.localIp
|
||||||
|
import Main.qq
|
||||||
|
import Main.sessionKey
|
||||||
import jpcap.JpcapCaptor
|
import jpcap.JpcapCaptor
|
||||||
import jpcap.packet.IPPacket
|
import jpcap.packet.IPPacket
|
||||||
import jpcap.packet.UDPPacket
|
import jpcap.packet.UDPPacket
|
||||||
@ -19,13 +22,12 @@ import net.mamoe.mirai.utils.io.*
|
|||||||
import net.mamoe.mirai.utils.toUHexString
|
import net.mamoe.mirai.utils.toUHexString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 抓包分析器
|
* 抓包分析器.
|
||||||
|
* 设置好 [sessionKey], [localIp] 和 [qq] 后运行即可开始抓包和自动解密
|
||||||
*
|
*
|
||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
object Main {
|
object Main {
|
||||||
const val localIp = "192.168.3."
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val devices = JpcapCaptor.getDeviceList()
|
val devices = JpcapCaptor.getDeviceList()
|
||||||
@ -77,8 +79,9 @@ object Main {
|
|||||||
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
|
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
|
||||||
* 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey`
|
* 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 sessionKey: ByteArray = "1D 1E 71 68 B9 41 FD 5B F3 5A 3F 71 87 B5 86 CB".hexToBytes()
|
||||||
val qq: UInt = 1040400290u
|
const val qq: UInt = 1040400290u
|
||||||
|
const val localIp = "192.168.3."
|
||||||
|
|
||||||
fun dataReceived(data: ByteArray) {
|
fun dataReceived(data: ByteArray) {
|
||||||
//println("raw = " + data.toUHexString())
|
//println("raw = " + data.toUHexString())
|
||||||
|
Loading…
Reference in New Issue
Block a user