mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-07 16:40:43 +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.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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
sendPacket(packet.ResponsePacket(bot.qqAccount, sessionKey))
|
||||
}
|
||||
//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)
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
@ -88,6 +84,4 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
|
||||
this.sKeyRefresherJob = null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val UninitializedPacketId: UShort = 0u
|
||||
}
|
@ -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>
|
||||
|
@ -10,7 +10,7 @@ import kotlin.reflect.KClass
|
||||
* 临时数据包处理器
|
||||
* ```kotlin
|
||||
* session.addHandler<ClientTouchResponsePacket>{
|
||||
* toSend { OutgoingTouchPacket() }
|
||||
* toSend { TouchPacket() }
|
||||
* onExpect {//it: ClientTouchResponsePacket
|
||||
* //do sth.
|
||||
* }
|
||||
|
@ -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)
|
||||
|
@ -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}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()}")
|
||||
}
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
@ -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
|
||||
@ -17,9 +19,9 @@ fun main() {
|
||||
|
||||
// println("53 4B 4B 2F 6F 59 33 42 39 2F 68 56 54 45 4B 65 6A 5A 39 35 45 4D 7A 68 5A 2F 6F 4A 42 79 35 36 61 6F 50 59 32 6E 51 49 77 41 67 37 47 51 33 34 65 72 43 4C 41 72 50 4B 56 39 35 43 76 65 34 64".hexToBytes().stringOfWitch())
|
||||
println("53 4B 4B 2F 6F 59 33 42 39 2F 68 56 54 45 4B 65 6A 5A 39 35 45 4D 7A 68 5A 2F 6F 4A 42 79 35 36 61 6F 50 59 32 6E 51 49 77 41 67 37 47 51 33 34 65 72 43 4C 41 72 50 4B 56 39 35 43 76 65 34 64"
|
||||
.hexToBytes().unbase64().stringOfWitch())
|
||||
.hexToBytes().unbase64().stringOfWitch())
|
||||
println("53 4B 4B 2F 6F 59 33 42 39 2F 68 56 54 45 4B 65 6A 5A 39 35 45 4D 7A 68 5A 2F 6F 4A 42 79 35 36 61 6F 50 59 32 6E 51 49 77 41 67 37 47 51 33 34 65 72 43 4C 41 72 50 4B 56 39 35 43 76 65 34 64"
|
||||
.hexToBytes().unbase64().toUHexString())
|
||||
.hexToBytes().unbase64().toUHexString())
|
||||
|
||||
//base64解密结果 48 A2 BF A1 8D C1 F7 F8 55 4C 42 9E 8D 9F 79 10 CC E1 67 FA 09 07 2E 7A 6A 83 D8 DA 74 08 C0 08 3B 19 0D F8 7A B0 8B 02 B3 CA 57 DE 42 BD EE 1D
|
||||
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user