From 7ca62bb0c89a38db186a05e83a1904b6d30f04e3 Mon Sep 17 00:00:00 2001 From: Him188moe <Him188> Date: Mon, 2 Sep 2019 22:33:23 +0800 Subject: [PATCH] Updated verification code processing --- .../main/java/net/mamoe/mirai/MiraiMain.java | 18 +-- .../java/net/mamoe/mirai/MiraiServer.java | 70 ++------- .../src/main/java/net/mamoe/mirai/Robot.java | 17 ++- .../java/net/mamoe/mirai/contact/Contact.kt | 2 +- .../java/net/mamoe/mirai/contact/Group.kt | 86 ++++++----- .../main/java/net/mamoe/mirai/contact/Lazy.kt | 17 --- .../main/java/net/mamoe/mirai/contact/QQ.kt | 5 +- .../net/mamoe/mirai/message/defaults/At.java | 6 +- .../mirai/network/RobotNetworkHandler.kt | 117 ++++++++------- .../mamoe/mirai/network/packet/AccountInfo.kt | 2 +- .../mirai/network/packet/ClientPacket.kt | 31 +++- .../mamoe/mirai/network/packet/Heartbeat.kt | 2 +- .../mirai/network/packet/MessageEvent.kt | 2 +- .../net/mamoe/mirai/network/packet/SKey.kt | 4 +- .../mamoe/mirai/network/packet/ServerEvent.kt | 20 ++- .../mirai/network/packet/ServerPacket.kt | 10 +- .../net/mamoe/mirai/network/packet/Session.kt | 2 +- .../net/mamoe/mirai/network/packet/Touch.kt | 4 +- .../mirai/network/packet/VerificationCode.kt | 98 +++++++++++++ .../network/packet/login/ClientLoginPacket.kt | 15 +- .../packet/login/ClientLoginStatusPacket.kt | 2 +- .../ClientLoginVerificationCodePacket.kt | 41 ------ ...oginResponseVerificationCodeInitPacket.kt} | 13 +- .../message/ClientSendFriendMessagePacket.kt | 10 +- .../message/ClientSendGroupMessagePacket.kt | 6 +- .../ServerVerificationCodePacket.kt | 44 ------ .../net/mamoe/mirai/utils/ContactList.java | 2 +- .../main/java/net/mamoe/mirai/utils/Utils.kt | 2 + .../utils/config/MiraiConfigSection.java | 4 +- mirai-core/src/test/java/HexComparator.java | 133 +++++++++++++----- mirai-core/src/test/java/TestKt.kt | 8 ++ 31 files changed, 435 insertions(+), 358 deletions(-) delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt rename mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/{ServerLoginResponseVerificationCodePacket.kt => ServerLoginResponseVerificationCodeInitPacket.kt} (61%) delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt create mode 100644 mirai-core/src/test/java/TestKt.kt diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java index 77c77cbfd..d959f504a 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java @@ -1,28 +1,14 @@ package net.mamoe.mirai; -import net.mamoe.mirai.utils.config.MiraiConfig; -import net.mamoe.mirai.utils.config.MiraiConfigSection; - /** * @author Him188moe */ public final class MiraiMain { private static MiraiServer server; + public static void main(String[] args) { server = new MiraiServer(); - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - server.shutdown(); - })); - MiraiConfig config = new MiraiConfig("QQ.yml"); - MiraiConfigSection<Object> data = config.getSection("123123"); - data.put("account","123123a"); - try { - Robot robot = new Robot(data); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - - + Runtime.getRuntime().addShutdownHook(new Thread(() -> server.shutdown())); } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java index 6ba54eb76..a768ff60f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java @@ -5,7 +5,6 @@ import net.mamoe.mirai.event.MiraiEventManager; import net.mamoe.mirai.event.events.server.ServerDisableEvent; import net.mamoe.mirai.event.events.server.ServerEnableEvent; import net.mamoe.mirai.network.RobotNetworkHandler; -import net.mamoe.mirai.network.packet.ClientTouchPacket; import net.mamoe.mirai.task.MiraiTaskManager; import net.mamoe.mirai.utils.LoggerTextFormat; import net.mamoe.mirai.utils.MiraiLogger; @@ -17,7 +16,6 @@ import net.mamoe.mirai.utils.setting.MiraiSettingMapSection; import java.io.File; import java.io.IOException; -import java.util.LinkedList; import java.util.Scanner; public class MiraiServer { @@ -119,62 +117,20 @@ public class MiraiServer { getLogger().info("ready to connect"); - /* - MiraiConfigSection section = new MiraiConfigSection<MiraiConfigSection<String>>(){{ - put("1",new MiraiConfigSection<>(){{ - put("1","0"); - }}); - }}; + this.qqs.keySet().stream().map(key -> this.qqs.getSection(key)).forEach(section -> { + try { + Robot robot = new Robot(section); + RobotNetworkHandler robotNetworkHandler = robot.getHandler(); + robotNetworkHandler.setServerIP("14.116.136.106"); + robotNetworkHandler.touch$mirai_core(); - this.qqs.put("test",section); - this.qqs.save(); - */ - - - MiraiConfigSection<MiraiConfigSection> x = this.qqs.getTypedSection("test"); - //System.out.println(x.getSection("1").getInt("1")); - - /* - System.out.println(v); - - System.out.println(v.get("1111")); - */ - - - Robot robot = new Robot(1994701021, "xiaoqqq", new LinkedList<>()); - RobotNetworkHandler robotNetworkHandler = robot.getHandler(); - try { - //System.out.println(Protocol.Companion.getSERVER_IP().get(3)); - //System.out.println(Protocol.Companion.getSERVER_IP().toString()); - - robotNetworkHandler.setServerIP("14.116.136.106"); - robotNetworkHandler.sendPacket(new ClientTouchPacket(1994701021, "14.116.136.106")); - while (true) ; - //robotNetworkHandler.connect("14.116.136.106"); - //robotNetworkHandler.connect(Protocol.Companion.getSERVER_IP().get(2)); - //robotNetworkHandler.connect("125.39.132.242"); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } -/* - System.out.println("network test"); - try { - - - MiraiUDPServer server = new MiraiUDPServer(); - MiraiUDPClient client = new MiraiUDPClient(InetAddress.getLocalHost(),9999,MiraiNetwork.getAvailablePort()); - this.getTaskManager().repeatingTask(() -> { - byte[] sendInfo = "test test".getBytes(StandardCharsets.UTF_8); - try { - client.send(new DatagramPacket(sendInfo,sendInfo.length)); - } catch (IOException e) { - e.printStackTrace(); - } - },300); - } catch (IOException e) { - e.printStackTrace(); - }*/ + Robot.instances.add(robot); + } catch (Throwable e) { + e.printStackTrace(); + getLogger().error("Could not load QQ robots config!"); + System.exit(1); + } + }); } private void initSetting(File setting) { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java index fa6d90e37..20b6c922a 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java @@ -9,11 +9,13 @@ import net.mamoe.mirai.utils.config.MiraiConfigSection; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; public class Robot { + public static final List<Robot> instances = Collections.synchronizedList(new LinkedList<>()); - private final int qqNumber; + private final long qqNumber; private final String password; @Getter private final RobotNetworkHandler handler; @@ -31,38 +33,41 @@ public class Robot { return owners.contains(ownerName); } + public long getQQNumber() { + return qqNumber; + } public Robot(MiraiConfigSection<Object> data) throws Throwable { this( - data.getIntOrThrow("account", () -> new IllegalArgumentException("account")), + data.getLongOrThrow("account", () -> new IllegalArgumentException("account")), data.getStringOrThrow("password", () -> new IllegalArgumentException("password")), data.getAsOrDefault("owners", ArrayList::new) ); } - public Robot(int qqNumber, String password, List<String> owners) { + public Robot(long qqNumber, String password, List<String> owners) { this.qqNumber = qqNumber; this.password = password; this.owners = Collections.unmodifiableList(owners); this.handler = new RobotNetworkHandler(this, this.qqNumber, this.password); } - public QQ getQQ(int qqNumber) { + public QQ getQQ(long qqNumber) { if (!this.qqs.containsKey(qqNumber)) { this.qqs.put(qqNumber, new QQ(qqNumber)); } return this.qqs.get(qqNumber); } - public Group getGroup(int groupNumber) { + public Group getGroup(long groupNumber) { if (!this.groups.containsKey(groupNumber)) { this.groups.put(groupNumber, new Group(groupNumber)); } return groups.get(groupNumber); } - public Group getGroupByGroupId(int groupId) { + public Group getGroupByGroupId(long groupId) { return getGroup(Group.Companion.groupIdToNumber(groupId)); } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt index 844c5c050..fa1a475c1 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt @@ -8,7 +8,7 @@ import net.mamoe.mirai.message.defaults.PlainText * * @author Him188moe */ -abstract class Contact(val number: Int) { +abstract class Contact(val number: Long) { /** * Async diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt index 835a1b0a2..2d8677058 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt @@ -3,14 +3,10 @@ package net.mamoe.mirai.contact import net.mamoe.mirai.message.Message import net.mamoe.mirai.utils.ContactList -class Group(number: Int) : Contact(number) { +class Group(number: Long) : Contact(number) { val groupId = groupNumberToId(number) val members = ContactList<QQ>() - init { - Instances.groups.add(this) - } - override fun sendMessage(message: Message) { } @@ -20,38 +16,38 @@ class Group(number: Int) : Contact(number) { } companion object { - fun groupNumberToId(number: Int): Int { - val left: Int = number.toString().let { + fun groupNumberToId(number: Long): Long { + val left: Long = number.toString().let { if (it.length < 6) { return@groupNumberToId number } - it.substring(0, it.length - 6).toInt() + it.substring(0, it.length - 6).toLong() } - val right: Int = number.toString().let { - it.substring(it.length - 6).toInt() + val right: Long = number.toString().let { + it.substring(it.length - 6).toLong() } return when (left) { in 1..10 -> { - ((left + 202).toString() + right.toString()).toInt() + ((left + 202).toString() + right.toString()).toLong() } in 11..19 -> { - ((left + 469).toString() + right.toString()).toInt() + ((left + 469).toString() + right.toString()).toLong() } in 20..66 -> { - ((left + 208).toString() + right.toString()).toInt() + ((left + 208).toString() + right.toString()).toLong() } in 67..156 -> { - ((left + 1943).toString() + right.toString()).toInt() + ((left + 1943).toString() + right.toString()).toLong() } in 157..209 -> { - ((left + 199).toString() + right.toString()).toInt() + ((left + 199).toString() + right.toString()).toLong() } in 210..309 -> { - ((left + 389).toString() + right.toString()).toInt() + ((left + 389).toString() + right.toString()).toLong() } in 310..499 -> { - ((left + 349).toString() + right.toString()).toInt() + ((left + 349).toString() + right.toString()).toLong() } else -> number } @@ -62,60 +58,60 @@ class Group(number: Int) : Contact(number) { groupNumberToId(580266363) } - fun groupIdToNumber(id: Int): Int { - var left: Int = id.toString().let { + fun groupIdToNumber(id: Long): Long { + var left: Long = id.toString().let { if (it.length < 6) { return@groupIdToNumber id } - it.substring(0 until it.length - 6).toInt() + it.substring(0 until it.length - 6).toLong() } return when (left) { in 203..212 -> { - val right: Int = id.toString().let { - it.substring(it.length - 6).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 6).toLong() } - ((left - 202).toString() + right.toString()).toInt() + ((left - 202).toString() + right.toString()).toLong() } in 480..488 -> { - val right: Int = id.toString().let { - it.substring(it.length - 6).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 6).toLong() } - ((left - 469).toString() + right.toString()).toInt() + ((left - 469).toString() + right.toString()).toLong() } in 2100..2146 -> { - val right: Int = id.toString().let { - it.substring(it.length - 7).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 7).toLong() } - left = left.toString().substring(0 until 3).toInt() - ((left - 208).toString() + right.toString()).toInt() + left = left.toString().substring(0 until 3).toLong() + ((left - 208).toString() + right.toString()).toLong() } in 2010..2099 -> { - val right: Int = id.toString().let { - it.substring(it.length - 6).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 6).toLong() } - ((left - 1943).toString() + right.toString()).toInt() + ((left - 1943).toString() + right.toString()).toLong() } in 2147..2199 -> { - val right: Int = id.toString().let { - it.substring(it.length - 7).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 7).toLong() } - left = left.toString().substring(0 until 3).toInt() - ((left - 199).toString() + right.toString()).toInt() + left = left.toString().substring(0 until 3).toLong() + ((left - 199).toString() + right.toString()).toLong() } in 4100..4199 -> { - val right: Int = id.toString().let { - it.substring(it.length - 7).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 7).toLong() } - left = left.toString().substring(0 until 3).toInt() - ((left - 389).toString() + right.toString()).toInt() + left = left.toString().substring(0 until 3).toLong() + ((left - 389).toString() + right.toString()).toLong() } in 3800..3989 -> { - val right: Int = id.toString().let { - it.substring(it.length - 7).toInt() + val right: Long = id.toString().let { + it.substring(it.length - 7).toLong() } - left = left.toString().substring(0 until 3).toInt() - ((left - 349).toString() + right.toString()).toInt() + left = left.toString().substring(0 until 3).toLong() + ((left - 349).toString() + right.toString()).toLong() } else -> id } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt deleted file mode 100644 index cecd6001c..000000000 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.mamoe.mirai.contact - - -fun Int.asQQ(): QQ = Instances.qqs.stream().filter { t: QQ? -> t?.number?.equals(this)!! }.findAny().orElse(QQ(this))!! - -fun Int.asGroup(): Group = Instances.groups.stream().filter { t: Group? -> t?.number?.equals(this)!! }.findAny().orElse(Group(this))!! - -fun String.withImage(id: String, type: String) = "{$id}.$type" - -fun String.withAt(qq: Int) = qq.asQQ().at() - -fun String.withAt(qq: QQ) = qq.at() - -object Instances { - var qqs = arrayListOf<QQ>() - var groups = arrayListOf<Group>() -} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt index 5638a2de2..e7a0cf537 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt @@ -6,10 +6,7 @@ import net.mamoe.mirai.message.defaults.At /** * @author Him188moe */ -class QQ(number: Int) : Contact(number) { - init { - Instances.qqs.add(this) - } +class QQ(number: Long) : Contact(number) { override fun sendMessage(message: Message) { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java index 088a98a30..003d40850 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java @@ -10,17 +10,17 @@ import java.util.Objects; * @author Him188moe */ public final class At extends Message { - private final int target; + private final long target; public At(@NotNull QQ target) { this(Objects.requireNonNull(target).getNumber()); } - public At(int target) { + public At(long target) { this.target = target; } - public int getTarget() { + public long getTarget() { return target; } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt index 7d28047fc..0db821a4f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt @@ -1,6 +1,5 @@ package net.mamoe.mirai.network -import net.mamoe.mirai.MiraiServer import net.mamoe.mirai.Robot import net.mamoe.mirai.contact.Group import net.mamoe.mirai.event.events.qq.FriendMessageEvent @@ -10,12 +9,8 @@ import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.message.ClientSendGroupMessagePacket import net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket -import net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacket -import net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacketEncrypted import net.mamoe.mirai.task.MiraiThreadPool import net.mamoe.mirai.utils.* -import java.io.ByteArrayInputStream -import java.io.FileOutputStream import java.net.DatagramPacket import java.net.DatagramSocket import java.net.InetSocketAddress @@ -28,9 +23,7 @@ import java.util.concurrent.TimeUnit * @author Him188moe */ @ExperimentalUnsignedTypes -class RobotNetworkHandler(val robot: Robot, val number: Int, private val password: String) { - - private var sequence: Int = 0 +class RobotNetworkHandler(val robot: Robot, val number: Long, private val password: String) { var socket: DatagramSocket = DatagramSocket((15314 + Math.random() * 100).toInt()) @@ -39,33 +32,7 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor serverAddress = InetSocketAddress(value, 8000) field = value - socket.close() - socket = DatagramSocket((15314 + Math.random() * 100).toInt()) - socket.connect(this.serverAddress) - val zeroByte: Byte = 0 - Thread { - while (true) { - val dp1 = DatagramPacket(ByteArray(2048), 2048) - try { - socket.receive(dp1) - } catch (e: Exception) { - if (e.message == "socket closed") { - return@Thread - } - } - MiraiThreadPool.getInstance().submit { - var i = dp1.data.size - 1; - while (dp1.data[i] == zeroByte) { - --i - } - try { - onPacketReceived(ServerPacket.ofByteArray(dp1.data.copyOfRange(0, i + 1))) - } catch (e: Exception) { - e.printStackTrace() - } - } - } - }.start() + restartSocket() } private lateinit var serverAddress: InetSocketAddress @@ -78,6 +45,10 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor private var tlv0105: ByteArray private lateinit var _0828_rec_decr_key: ByteArray + private var verificationCodeSequence: Int = 0//这两个验证码使用 + private var verificationCodeCache: ByteArray? = null//每次包只发一部分验证码来 + private var verificationCodeCacheCount: Int = 0// + private lateinit var verificationToken: ByteArray private lateinit var sessionKey: ByteArray//这两个是登录成功后得到的 private lateinit var sKey: String @@ -104,6 +75,40 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor private var md5_32: ByteArray = getRandomKey(32) + internal fun touch() { + this.sendPacket(ClientTouchPacket(this.number, this.serverIP)) + } + + private fun restartSocket() { + socket.close() + socket = DatagramSocket((15314 + Math.random() * 100).toInt()) + socket.connect(this.serverAddress) + val zeroByte: Byte = 0 + Thread { + while (true) { + val dp1 = DatagramPacket(ByteArray(2048), 2048) + try { + socket.receive(dp1) + } catch (e: Exception) { + if (e.message == "socket closed") { + return@Thread + } + } + MiraiThreadPool.getInstance().submit { + var i = dp1.data.size - 1; + while (dp1.data[i] == zeroByte) { + --i + } + try { + onPacketReceived(ServerPacket.ofByteArray(dp1.data.copyOfRange(0, i + 1))) + } catch (e: Exception) { + e.printStackTrace() + } + } + } + }.start() + } + @ExperimentalUnsignedTypes internal fun onPacketReceived(packet: ServerPacket) { packet.decode() @@ -131,22 +136,44 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor return } - is ServerLoginResponseVerificationCodePacket -> { + is ServerLoginResponseVerificationCodeInitPacket -> { //[token00BA]来源之一: 验证码 this.token00BA = packet.token00BA + this.verificationCodeCache = packet.verifyCodePart1 - with(MiraiServer.getInstance().parentFolder + "verifyCode.png") { - ByteArrayInputStream(packet.verifyCode).transferTo(FileOutputStream(this)) - println("验证码已写入到 " + this.path) - } if (packet.unknownBoolean != null && packet.unknownBoolean!!) { - this.sequence = 1 - sendPacket(ClientLoginVerificationCodePacket(this.number, this.token0825, this.sequence, this.token00BA)) + this.verificationCodeSequence = 1 + sendPacket(ClientVerificationCodeTransmissionRequestPacket(1, this.number, this.token0825, this.verificationCodeSequence, this.token00BA)) } } + is ServerVerificationCodeRepeatPacket -> {//todo 这个名字正确么 + this.tgtgtKey = packet.tgtgtKeyUpdate + this.token00BA = packet.token00BA + sendPacket(ClientLoginResendPacket3105(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA)) + } + + is ServerVerificationCodeTransmissionPacket -> { + this.verificationCodeSequence = 0 + this.verificationCodeCache = this.verificationCodeCache!! + packet.verificationCodePart2 + + this.verificationToken = packet.verificationToken + this.verificationCodeCacheCount = packet.count + + this.token00BA = packet.token00BA + this.verificationCodeCache + + + if (packet.transmissionCompleted) { + this.verificationCodeCache + TODO("验证码好了") + } else { + sendPacket(ClientVerificationCodeTransmissionRequestPacket(packet.count, this.number, this.token0825, this.verificationCodeSequence, this.token00BA)) + } + } + is ServerLoginResponseSuccessPacket -> { this._0828_rec_decr_key = packet._0828_rec_decr_key sendPacket(ClientSessionRequestPacket(this.number, this.serverIP, this.loginIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105)) @@ -190,10 +217,6 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor } } - is ServerVerificationCodePacket -> { - this.sequence++ - - } is ServerSessionKeyResponsePacket -> { this.sessionKey = packet.sessionKey @@ -267,7 +290,7 @@ class RobotNetworkHandler(val robot: Robot, val number: Int, private val passwor is ServerMessageEventPacketRaw -> onPacketReceived(packet.analyze()) - is ServerVerificationCodePacketEncrypted -> onPacketReceived(packet.decrypt(this.token00BA)) + is ServerVerificationCodePacketEncrypted -> onPacketReceived(packet.decrypt()) is ServerLoginResponseVerificationCodePacketEncrypted -> onPacketReceived(packet.decrypt()) is ServerLoginResponseResendPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) is ServerLoginResponseSuccessPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt index 85ffc41dc..90d50c89e 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt @@ -12,7 +12,7 @@ import java.io.DataInputStream @ExperimentalUnsignedTypes @PacketId("00 5C") class ClientAccountInfoRequestPacket( - private val qq: Int, + private val qq: Long, private val sessionKey: ByteArray ) : ClientPacket() { override fun encode() { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt index 29682026d..6c18807e8 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt @@ -119,13 +119,18 @@ fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutp this.write(TEACryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }, key)) } +@ExperimentalUnsignedTypes +fun DataOutputStream.encryptAndWrite(keyHex: String, encoder: (ByteArrayDataOutputStream) -> Unit) { + this.encryptAndWrite(keyHex.hexToBytes(), encoder) +} + fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: (ByteArrayDataOutputStream) -> Unit) { this.write(cryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() })) } @ExperimentalUnsignedTypes @Throws(IOException::class) -fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) { +fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) { ByteArrayDataOutputStream().let { it.writeHex("12 12 12 12")//it.writeRandom(4) todo it.writeHex("00 02") @@ -134,7 +139,7 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log it.writeHex("00 00 01") val md5_1 = md5(password); - val md5_2 = md5(md5_1 + "00 00 00 00".hexToBytes() + qq.toByteArray()) + val md5_2 = md5(md5_1 + "00 00 00 00".hexToBytes() + qq.toUInt().toByteArray()) println(md5_1.toUByteArray().toUHexString()) println(md5_2.toUByteArray().toUHexString()) it.write(md5_1) @@ -193,6 +198,17 @@ fun Int.toByteArray(): ByteArray = byteArrayOf( (this.ushr(0) and 0xFF).toByte() ) +/** + * 255u -> 00 00 00 FF + */ +@ExperimentalUnsignedTypes +fun UInt.toByteArray(): ByteArray = byteArrayOf( + (this.shr(24) and 255u).toByte(), + (this.shr(16) and 255u).toByte(), + (this.shr(8) and 255u).toByte(), + (this.shr(0) and 255u).toByte() +) + /** * 255 -> FF 00 00 00 */ @@ -225,7 +241,14 @@ fun DataOutputStream.writeRandom(length: Int) { } } +@ExperimentalUnsignedTypes @Throws(IOException::class) -fun DataOutputStream.writeQQ(qq: Int) { - this.writeInt(qq) +fun DataOutputStream.writeQQ(qq: Long) { + this.write(qq.toUInt().toByteArray()) +} + +@ExperimentalUnsignedTypes +@Throws(IOException::class) +fun DataOutputStream.writeGroup(groupIdOrGroupNumber: Long) { + this.write(groupIdOrGroupNumber.toUInt().toByteArray()) } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt index 8a40a441d..d8b1b8040 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt @@ -10,7 +10,7 @@ import java.io.IOException @ExperimentalUnsignedTypes @PacketId("00 58") class ClientHeartbeatPacket( - private val qq: Int, + private val qq: Long, private val sessionKey: ByteArray ) : ClientPacket() { @Throws(IOException::class) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt index 2657662ee..001cf7571 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt @@ -12,7 +12,7 @@ import java.io.DataInputStream @PacketId("")//随后写入 @ExperimentalUnsignedTypes class ClientMessageResponsePacket( - private val qq: Int, + private val qq: Long, private val packetIdFromServer: ByteArray, private val sessionKey: ByteArray, private val eventIdentity: ByteArray diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt index c5a1d4905..76b181fca 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt @@ -11,7 +11,7 @@ import java.io.DataInputStream @ExperimentalUnsignedTypes @PacketId("00 1D") class ClientSKeyRequestPacket( - private val qq: Int, + private val qq: Long, private val sessionKey: ByteArray ) : ClientPacket() { override fun encode() { @@ -31,7 +31,7 @@ class ClientSKeyRequestPacket( @PacketId("00 1D") @ExperimentalUnsignedTypes class ClientSKeyRefreshmentRequestPacket( - private val qq: Int, + private val qq: Long, private val sessionKey: ByteArray ) : ClientPacket() { override fun encode() { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt index 8d73cc493..02fcfc719 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt @@ -39,8 +39,8 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr } class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { - var groupNumber: Int = 0 - var qq: Int = 0 + var groupNumber: Long = 0 + var qq: Long = 0 lateinit var message: String lateinit var messageType: MessageType @@ -58,9 +58,10 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, OTHER, } + @ExperimentalUnsignedTypes override fun decode() { - groupNumber = this.input.goto(51).readInt() - qq = this.input.goto(56).readInt() + groupNumber = this.input.goto(51).readInt().toLong() + qq = this.input.goto(56).readLong().toUInt().toLong() val fontLength = this.input.goto(108).readShort() //println(this.input.goto(110 + fontLength).readNBytesAt(2).toUHexString())//always 00 00 @@ -142,7 +143,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, } class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { - var qq: Int = 0 + var qq: Long = 0 lateinit var message: MessageChain @@ -153,7 +154,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray println(input.readAllBytes().toUHexString()) input.goto(0) - qq = input.readIntAt(0) + qq = input.readIntAt(0).toLong() val msgLength = input.readShortAt(22) val fontLength = input.readShortAt(93 + msgLength) val offset = msgLength + fontLength @@ -164,6 +165,11 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray } } +/* +3E 03 3F A2 76 E4 B8 DD 00 09 7C 3F 64 5C 2A 60 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E4 5D 6B A8 F6 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A8 F6 08 7E 90 CE 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 +3E 03 3F A2 76 E4 B8 DD 00 03 5F 85 64 5C 2A A4 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E5 5D 6B A9 16 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A9 17 1B B3 4D D7 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 + + */ /* @@ -171,7 +177,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray backup class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { - var qq: Int = 0 + var qq: Long = 0 lateinit var message: String diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt index c3e0e2e3a..ced9db2b2 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt @@ -3,7 +3,6 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket -import net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacketEncrypted import net.mamoe.mirai.utils.getAllDeclaredFields import net.mamoe.mirai.utils.hexToBytes import net.mamoe.mirai.utils.toUHexString @@ -150,6 +149,15 @@ fun <N : Number> DataInputStream.readNBytesAt(position: N, length: Int): ByteArr return this.readNBytes(length) } +fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray { + return this.readNBytes(length.toInt()) +} + +fun DataInputStream.readNBytesIn(range: IntRange): ByteArray { + this.goto(range.first) + return this.readNBytes(range.last - range.first + 1) +} + fun <N : Number> DataInputStream.readIntAt(position: N): Int { this.goto(position) return this.readInt(); diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt index a6eb7bf81..4f55c4e88 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt @@ -14,7 +14,7 @@ import java.net.InetAddress @ExperimentalUnsignedTypes @PacketId("08 28 04 34") class ClientSessionRequestPacket( - private val qq: Int, + private val qq: Long, private val serverIp: String, private val loginIP: String, private val md5_32: ByteArray, diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt index 5654f791c..bf3624e84 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt @@ -76,7 +76,7 @@ class ServerTouchResponsePacketEncrypted(private val type: ServerTouchResponsePa */ @ExperimentalUnsignedTypes @PacketId("08 25 31 01") -class ClientTouchPacket(val qq: Int, val serverIp: String) : ClientPacket() { +class ClientTouchPacket(val qq: Long, val serverIp: String) : ClientPacket() { @ExperimentalUnsignedTypes @Throws(IOException::class) override fun encode() { @@ -108,7 +108,7 @@ class ClientTouchPacket(val qq: Int, val serverIp: String) : ClientPacket() { */ @ExperimentalUnsignedTypes @PacketId("08 25 31 02") -class ClientServerRedirectionPacket(private val serverIP: String, private val qq: Int) : ClientPacket() { +class ClientServerRedirectionPacket(private val serverIP: String, private val qq: Long) : ClientPacket() { @ExperimentalUnsignedTypes override fun encode() { this.writeQQ(qq) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt new file mode 100644 index 000000000..4684f356b --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt @@ -0,0 +1,98 @@ +package net.mamoe.mirai.network.packet + +import net.mamoe.mirai.network.Protocol +import net.mamoe.mirai.utils.* +import java.io.DataInputStream + + +@ExperimentalUnsignedTypes +@PacketId("00 BA 31") +class ClientVerificationCodeTransmissionRequestPacket(//todo 这个包可能有问题. + private val count: Int, + private val qq: Long, + private val token0825: ByteArray, + private val verificationSequence: Int, + private val token00BA: ByteArray +) : ClientPacket() { + override fun encode() { + this.writeByte(count)//part of packet id + + this.writeQQ(qq) + this.writeHex(Protocol._fixVer) + this.writeHex(Protocol._00BaKey) + this.encryptAndWrite(Protocol._00BaKey) { + it.writeHex("00 02 00 00 08 04 01 E0") + it.writeHex(Protocol._0825data2) + it.writeHex("00 00 38") + it.write(token0825) + it.writeHex("01 03 00 19") + it.writeHex(Protocol.publicKey) + it.writeHex("13 00 05 00 00 00 00") + it.writeByte(verificationSequence) + it.writeHex("00 28") + it.write(token00BA) + it.writeHex("00 10") + it.writeHex(Protocol._00BaFixKey) + } + } +} + +/** + * @author Him188moe + */ +class ServerVerificationCodeTransmissionPacket(input: DataInputStream, val dataSize: Int, val packetId: ByteArray) : ServerVerificationCodePacket(input) { + + lateinit var verificationCodePart2: ByteArray + lateinit var verificationToken: ByteArray//56bytes + var transmissionCompleted: Boolean = false//验证码是否已经传输完成 + lateinit var token00BA: ByteArray//40 bytes + var count: Int = 0 + + @ExperimentalUnsignedTypes + override fun decode() { + this.verificationToken = this.input.readNBytesAt(10, 56) + + val length = this.input.readShortAt(66) + this.verificationCodePart2 = this.input.readNBytes(length) + + this.input.skip(2) + this.transmissionCompleted = this.input.readBoolean() + + this.token00BA = this.input.readNBytesAt(dataSize - 57, 40) + this.count = byteArrayOf(0, 0, packetId[2], packetId[3]).toUHexString().hexToInt() + } +} + +/** + * @author Him188moe + */ +class ServerVerificationCodeRepeatPacket(input: DataInputStream) : ServerVerificationCodePacket(input) { + + lateinit var token00BA: ByteArray//56 bytes + lateinit var tgtgtKeyUpdate: ByteArray + + @ExperimentalUnsignedTypes + override fun decode() { + token00BA = this.input.readNBytesAt(10, 56) + tgtgtKeyUpdate = getRandomKey(16) + } +} + +abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPacket(input) + +class ServerVerificationCodePacketEncrypted(input: DataInputStream) : ServerPacket(input) { + override fun decode() { + + } + + @ExperimentalUnsignedTypes + fun decrypt(): ServerVerificationCodePacket { + this.input goto 14 + val data = TEACryptor.decrypt(Protocol._00BaKey.hexToBytes(), this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }) + return if (data.size == 95) { + ServerVerificationCodeRepeatPacket(data.dataInputStream()) + } else { + ServerVerificationCodeTransmissionPacket(data.dataInputStream(), data.size, this.input.readNBytesAt(3, 4)) + } + } +} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt index c58e1c6d4..2330c1d30 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt @@ -18,7 +18,7 @@ import java.io.DataOutputStream @ExperimentalUnsignedTypes @TestedSuccessfully class ClientPasswordSubmissionPacket( - private val qq: Int, + private val qq: Long, private val password: String, private val loginTime: Int, private val loginIP: String, @@ -43,17 +43,22 @@ class ClientPasswordSubmissionPacket( @PacketId("08 36 31 04") @ExperimentalUnsignedTypes -class ClientLoginResendPacket3104(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) +class ClientLoginResendPacket3104(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv_0006_encr) +@PacketId("08 36 31 05") +@ExperimentalUnsignedTypes +class ClientLoginResendPacket3105(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) + : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, null) + @PacketId("08 36 31 06") @ExperimentalUnsignedTypes -class ClientLoginResendPacket3106(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) +class ClientLoginResendPacket3106(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv_0006_encr: ByteArray? = null) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv_0006_encr) @ExperimentalUnsignedTypes open class ClientLoginResendPacket internal constructor( - val qq: Int, + val qq: Long, val password: String, val loginTime: Int, val loginIP: String, @@ -91,7 +96,7 @@ open class ClientLoginResendPacket internal constructor( * @author Him188moe */ @ExperimentalUnsignedTypes -private fun DataOutputStream.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv_0006_encr: ByteArray? = null) { +private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv_0006_encr: ByteArray? = null) { //this.writeInt(System.currentTimeMillis().toInt()) this.writeHex("01 12")//tag diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt index e73b228d5..7c2b2eae3 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt @@ -10,7 +10,7 @@ import net.mamoe.mirai.utils.ClientLoginStatus @ExperimentalUnsignedTypes @PacketId("00 EC") class ClientLoginStatusPacket( - private val qq: Int, + private val qq: Long, private val sessionKey: ByteArray, private val loginStatus: ClientLoginStatus diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt deleted file mode 100644 index 751fa07bf..000000000 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt +++ /dev/null @@ -1,41 +0,0 @@ -package net.mamoe.mirai.network.packet.login - -import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.network.packet.* -import net.mamoe.mirai.utils.ByteArrayDataOutputStream -import net.mamoe.mirai.utils.TEACryptor - -/** - * @author Him188moe - */ -@PacketId("00 BA 31 01") -@ExperimentalUnsignedTypes -class ClientLoginVerificationCodePacket( - private val qq: Int, - private val token0825: ByteArray, - private val sequence: Int, - private val token00BA: ByteArray -) : ClientPacket() { - override fun encode() { - this.writeQQ(qq) - this.writeHex(Protocol.fixVer) - this.writeHex(Protocol._00BaKey) - this.write(TEACryptor.CRYPTOR_00BAKEY.encrypt(object : ByteArrayDataOutputStream() { - override fun toByteArray(): ByteArray { - this.writeHex("00 02 00 00 08 04 01 E0") - this.writeHex(Protocol._0825data2) - this.writeHex("00 00 38") - this.write(token0825) - this.writeHex("01 03 00 19") - this.writeHex(Protocol.publicKey) - this.writeHex("13 00 05 00 00 00 00") - this.writeVarInt(sequence.toUInt()) - this.writeHex("00 28") - this.write(token00BA) - this.writeHex("00 10") - this.writeHex(Protocol._00BaFixKey) - return super.toByteArray() - } - }.toByteArray())) - } -} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt similarity index 61% rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodePacket.kt rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt index 540b23f5a..1d6428c63 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt @@ -7,19 +7,22 @@ import net.mamoe.mirai.utils.TEACryptor import java.io.DataInputStream /** + * 收到这个包意味着需要验证码登录, 并且能得到验证码图片文件的一半 + * * @author Him188moe */ -class ServerLoginResponseVerificationCodePacket(input: DataInputStream, private val packetLength: Int) : ServerPacket(input) { +class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, private val packetLength: Int) : ServerPacket(input) { - lateinit var verifyCode: ByteArray + lateinit var verifyCodePart1: ByteArray lateinit var token00BA: ByteArray var unknownBoolean: Boolean? = null +//todo 也有可能这个包有问题, 也有可能 ClientVerificationCodeTransmissionRequestPacket. 检查 @ExperimentalUnsignedTypes override fun decode() { val verifyCodeLength = this.input.goto(78).readShort()//2bytes - this.verifyCode = this.input.readNBytes(verifyCodeLength.toInt()) + this.verifyCodePart1 = this.input.readNBytes(verifyCodeLength.toInt()) this.input.skip(1) @@ -34,9 +37,9 @@ class ServerLoginResponseVerificationCodePacketEncrypted(input: DataInputStream) } - fun decrypt(): ServerLoginResponseVerificationCodePacket { + fun decrypt(): ServerLoginResponseVerificationCodeInitPacket { this.input goto 14 val data = TEACryptor.CRYPTOR_SHARE_KEY.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }); - return ServerLoginResponseVerificationCodePacket(data.dataInputStream(), data.size) + return ServerLoginResponseVerificationCodeInitPacket(data.dataInputStream(), data.size) } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt index 905d3fd9b..6fa63d04d 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt @@ -11,10 +11,10 @@ import java.io.DataInputStream @PacketId("00 CD") @ExperimentalUnsignedTypes class ClientSendFriendMessagePacket( - val robotQQ: Int, - val targetQQ: Int, - val sessionKey: ByteArray, - val message: String + private val robotQQ: Long, + private val targetQQ: Long, + private val sessionKey: ByteArray, + private val message: String ) : ClientPacket() { override fun encode() { this.writeRandom(2)//part of packet id @@ -52,7 +52,7 @@ class ClientSendFriendMessagePacket( it.writeByte(0x01) it.writeShort(bytes.size) it.write(bytes) - }//todo check + } } } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt index 315814a29..2ef2a85cc 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt @@ -12,8 +12,8 @@ import java.io.DataInputStream @PacketId("00 02") @ExperimentalUnsignedTypes class ClientSendGroupMessagePacket( - private val groupId: Int,//不是 number - private val qq: Int, + private val groupId: Long,//不是 number + private val qq: Long, private val sessionKey: ByteArray, private val message: String ) : ClientPacket() { @@ -25,7 +25,7 @@ class ClientSendGroupMessagePacket( this.encryptAndWrite(sessionKey) { val bytes = message.toByteArray() it.writeByte(0x2A) - it.writeInt(groupId) + it.writeGroup(groupId) it.writeShort(56 + bytes.size) it.writeHex("00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00") diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt deleted file mode 100644 index 710c1c2a0..000000000 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt +++ /dev/null @@ -1,44 +0,0 @@ -package net.mamoe.mirai.network.packet.verification - -import net.mamoe.mirai.network.packet.ServerPacket -import net.mamoe.mirai.network.packet.dataInputStream -import net.mamoe.mirai.network.packet.goto -import net.mamoe.mirai.utils.TEACryptor -import java.io.DataInputStream - -/** - * @author Him188moe - */ -class ServerVerificationCodePacket(input: DataInputStream) : ServerPacket(input) { - - lateinit var verifyCode: ByteArray - lateinit var verifyToken: ByteArray - var unknownBoolean: Boolean? = null - lateinit var token00BA: ByteArray - var count: Int = 0 - - @ExperimentalUnsignedTypes - override fun decode() { - TODO() - val verifyCodeLength = this.input.goto(78).readShort()//2bytes - this.verifyCode = this.input.readNBytes(verifyCodeLength.toInt()) - - this.input.skip(1) - - this.unknownBoolean = this.input.readByte().toInt() == 1 - - //this.token00BA = this.input.goto(packetLength - 60).readNBytesAt(40) - } -} - -class ServerVerificationCodePacketEncrypted(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - - } - - fun decrypt(token00BA: ByteArray): ServerVerificationCodePacket { - this.input goto 14 - val data = TEACryptor.decrypt(token00BA, this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }); - return ServerVerificationCodePacket(data.dataInputStream()) - } -} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java index 2729890f2..6cfde9c52 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java @@ -6,5 +6,5 @@ import net.mamoe.mirai.utils.config.MiraiSynchronizedLinkedListMap; /** * @author Him188moe */ -public class ContactList<C extends Contact> extends MiraiSynchronizedLinkedListMap<Integer, C> { +public class ContactList<C extends Contact> extends MiraiSynchronizedLinkedListMap<Long, C> { } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt b/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt index 3fac69b21..72ceb4c1a 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt @@ -20,6 +20,8 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s @ExperimentalUnsignedTypes fun ByteArray.toUHexString(separator: String = " "): String = this.toUByteArray().toUHexString(separator) +fun ByteArray.__toUHexString(separator: String = " "): String = this.toUByteArray().toUHexString(separator) + @ExperimentalUnsignedTypes fun ByteArray.toUHexString(): String = this.toUByteArray().toUHexString() diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java index 196ddd59a..7005b3f59 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java @@ -126,10 +126,10 @@ public class MiraiConfigSection<T> extends MiraiSynchronizedLinkedListMap<String return result==null?defaultV:result.toString(); } - public String getStringOrThrow(String key, Callable<Throwable> throwableCallable) throws Throwable { + public String getStringOrThrow(String key, Supplier<Throwable> exceptionSupplier) throws Throwable { Object result = this.getOrDefault(key, null); if(result == null){ - throw throwableCallable.call(); + throw exceptionSupplier.get(); } return result.toString(); } diff --git a/mirai-core/src/test/java/HexComparator.java b/mirai-core/src/test/java/HexComparator.java index cabaeba5d..e3a1571ca 100644 --- a/mirai-core/src/test/java/HexComparator.java +++ b/mirai-core/src/test/java/HexComparator.java @@ -3,11 +3,17 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.ToString; import net.mamoe.mirai.network.Protocol; +import net.mamoe.mirai.network.packet.ClientPacketKt; +import net.mamoe.mirai.utils.UtilsKt; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; import java.lang.reflect.Field; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Scanner; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; @@ -32,15 +38,24 @@ public class HexComparator { private static final String BLUE = "\033[34m"; - public static final List<HexReader> consts = new LinkedList<>(){{ + public static final List<HexReader> consts = new LinkedList<>() {{ add(new HexReader("90 5E 39 DF 00 02 76 E4 B8 DD 00")); }}; private static class ConstMatcher { private static final List<Field> CONST_FIELDS = new LinkedList<>() {{ List.of(Protocol.class).forEach(aClass -> Arrays.stream(aClass.getDeclaredFields()).peek(this::add).forEach(Field::trySetAccessible)); + List.of(TestConsts.class).forEach(aClass -> Arrays.stream(aClass.getDeclaredFields()).peek(this::add).forEach(Field::trySetAccessible)); }}; + @SuppressWarnings({"unused", "NonAsciiCharacters"}) + private static class TestConsts { + private static final String 牛逼 = UtilsKt.__toUHexString("牛逼".getBytes(), " "); + private static final String _1994701021 = ClientPacketKt.toHexString(1994701021, " "); + private static final String _1040400290 = ClientPacketKt.toHexString(1040400290, " "); + private static final String _580266363 = ClientPacketKt.toHexString(580266363, " "); + } + private final List<Match> matches = new LinkedList<>(); private ConstMatcher(String hex) { @@ -89,6 +104,23 @@ public class HexComparator { } } + private static void buildConstNameChain(int length, ConstMatcher constMatcher, StringBuilder constNameBuilder) { + for (int i = 0; i < length; i++) { + constNameBuilder.append(" "); + String match = constMatcher.getMatchedConstName(i / 4); + if (match != null) { + int appendedNameLength = match.length(); + constNameBuilder.append(match); + while (constMatcher.getMatchedConstName(i++ / 4) != null) { + if (appendedNameLength-- <= 0) { + constNameBuilder.append(" "); + } + } + + } + } + } + private static String compare(String hex1s, String hex2s) { StringBuilder builder = new StringBuilder(); @@ -105,10 +137,17 @@ public class HexComparator { StringBuilder numberLine = new StringBuilder(); + StringBuilder hex1ConstName = new StringBuilder(); StringBuilder hex1b = new StringBuilder(); StringBuilder hex2b = new StringBuilder(); + StringBuilder hex2ConstName = new StringBuilder(); int dif = 0; + int length = Math.max(hex1.length, hex2.length) * 4; + buildConstNameChain(length, constMatcher1, hex1ConstName); + buildConstNameChain(length, constMatcher2, hex2ConstName); + + for (int i = 0; i < Math.max(hex1.length, hex2.length); ++i) { String h1 = null; String h2 = null; @@ -152,7 +191,7 @@ public class HexComparator { } } - numberLine.append(UNKNOWN).append(getNumber(i)).append(" "); + numberLine.append(UNKNOWN).append(getFixedNumber(i)).append(" "); hex1b.append(" ").append(h1).append(" "); hex2b.append(" ").append(h2).append(" "); if (isDif) { @@ -165,42 +204,46 @@ public class HexComparator { return (builder.append(" ").append(dif).append(" 个不同").append("\n") .append(numberLine).append("\n") + .append(hex1ConstName).append("\n") .append(hex1b).append("\n") - .append(hex2b)) + .append(hex2b).append("\n") + .append(hex2ConstName).append("\n") + ) .toString(); } - private static void doConstReplacement(StringBuilder builder){ + private static void doConstReplacement(StringBuilder builder) { String mirror = builder.toString(); HexReader hexs = new HexReader(mirror); - for (AtomicInteger i=new AtomicInteger(0);i.get()<builder.length();i.addAndGet(1)){ + for (AtomicInteger i = new AtomicInteger(0); i.get() < builder.length(); i.addAndGet(1)) { hexs.setTo(i.get()); consts.forEach(a -> { hexs.setTo(i.get()); List<Integer> posToPlaceColor = new LinkedList<>(); AtomicBoolean is = new AtomicBoolean(false); - a.readFully((c,d) -> { - if(c.equals(hexs.readHex())){ + a.readFully((c, d) -> { + if (c.equals(hexs.readHex())) { posToPlaceColor.add(d); - }else{ + } else { is.set(false); } }); - if(is.get()){ + if (is.get()) { AtomicInteger adder = new AtomicInteger(); posToPlaceColor.forEach(e -> { - builder.insert(e + adder.getAndAdd(BLUE.length()),BLUE); + builder.insert(e + adder.getAndAdd(BLUE.length()), BLUE); }); } }); } } - private static String getNumber(int number) { + + private static String getFixedNumber(int number) { if (number < 10) { return "00" + number; } @@ -210,8 +253,31 @@ public class HexComparator { return String.valueOf(number); } - public static void main(String[] args) { + private static String getClipboardString() { + Transferable trans = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); + if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) { + try { + return (String) trans.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + while (true) { + System.out.println("Hex1: "); + var hex1 = scanner.nextLine(); + System.out.println("Hex2: "); + var hex2 = scanner.nextLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + System.out.println(HexComparator.compare(hex1, hex2)); + System.out.println(); + } +/* System.out.println(HexComparator.compare( //mirai @@ -230,66 +296,63 @@ public class HexComparator { "6F 0B DF 92 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 55 35 05 8E C9 BA 16 D0 01 63 5B 59 4B 59 52 31 01 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 E9 E9 E9 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B AA BB CC DD EE FF AA BB CC\n\n\n" ));*/ } - - } -class HexReader{ +class HexReader { private String s; private int pos = 0; private int lastHaxPos = 0; - public HexReader(String s){ + public HexReader(String s) { this.s = s; } - public String readHex(){ + public String readHex() { boolean isStr = false; String next = ""; - for (;pos<s.length()-2;++pos){ + for (; pos < s.length() - 2; ++pos) { char s1 = ' '; - if(pos != 0){ + if (pos != 0) { s1 = this.s.charAt(0); } - char s2 = this.s.charAt(pos+1); - char s3 = this.s.charAt(pos+2); + char s2 = this.s.charAt(pos + 1); + char s3 = this.s.charAt(pos + 2); char s4 = ' '; - if(this.s.length() != (this.pos+3)){ - s4 = this.s.charAt(pos+3); + if (this.s.length() != (this.pos + 3)) { + s4 = this.s.charAt(pos + 3); } - if( + if ( Character.isSpaceChar(s1) && Character.isSpaceChar(s4) - && + && (Character.isDigit(s2) || Character.isAlphabetic(s2)) && (Character.isDigit(s3) || Character.isAlphabetic(s3)) - ){ - this.pos+=2; - this.lastHaxPos = this.pos+1; - return String.valueOf(s2) + String.valueOf(s3); + ) { + this.pos += 2; + this.lastHaxPos = this.pos + 1; + return String.valueOf(s2) + s3; } } return ""; } - public void readFully(BiConsumer<String, Integer> processor){ + public void readFully(BiConsumer<String, Integer> processor) { this.reset(); String nextHax = this.readHex(); - while (!nextHax.equals(" ")){ - processor.accept(nextHax,this.lastHaxPos); + while (!nextHax.equals(" ")) { + processor.accept(nextHax, this.lastHaxPos); nextHax = this.readHex(); } } - public void setTo(int pos){ + public void setTo(int pos) { this.pos = pos; } - public void reset(){ + public void reset() { this.pos = 0; } - } diff --git a/mirai-core/src/test/java/TestKt.kt b/mirai-core/src/test/java/TestKt.kt new file mode 100644 index 000000000..42878b5dc --- /dev/null +++ b/mirai-core/src/test/java/TestKt.kt @@ -0,0 +1,8 @@ +import net.mamoe.mirai.utils.toUHexString + +/** + * @author Him188moe + */ +fun main() { + println("牛逼".toByteArray().toUHexString()) +} \ No newline at end of file