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

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))
}
}
@ -88,6 +84,4 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
this.sKeyRefresherJob = null
}
}
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
@ -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

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