Commit 9fda59af authored by Him188moe's avatar Him188moe

Message analysis

parent 21a0df80
...@@ -4,8 +4,147 @@ package net.mamoe.mirai.message; ...@@ -4,8 +4,147 @@ package net.mamoe.mirai.message;
* @author Him188moe * @author Him188moe
*/ */
public enum FaceID { public enum FaceID {
// TODO: 2019/9/1 Face_jingya(0),
Face_piezui(1),
Face_se(2),
Face_fadai(3),
Face_deyi(4),
Face_liulei(5),
Face_haixiu(6),
Face_bizui(7),
Face_shui(8),
Face_daku(9),
Face_ganga(10),
Face_fanu(11),
Face_tiaopi(12),
Face_ciya(13),
Face_weixiao(14),
Face_nanguo(15),
Face_ku(16),
Face_zhuakuang(18),
Face_tu(19),
Face_touxiao(20),
Face_keai(21),
Face_baiyan(22),
Face_aoman(23),
Face_ji_e(24),
Face_kun(25),
Face_jingkong(26),
Face_liuhan(27),
Face_hanxiao(28),
Face_dabing(29),
Face_fendou(30),
Face_zhouma(31),
Face_yiwen(32),
Face_yun(34),
Face_zhemo(35),
Face_shuai(36),
Face_kulou(37),
Face_qiaoda(38),
Face_zaijian(39),
Face_fadou(41),
Face_aiqing(42),
Face_tiaotiao(43),
Face_zhutou(46),
Face_yongbao(49),
Face_dan_gao(53),
Face_shandian(54),
Face_zhadan(55),
Face_dao(56),
Face_zuqiu(57),
Face_bianbian(59),
Face_kafei(60),
Face_fan(61),
Face_meigui(63),
Face_diaoxie(64),
Face_aixin(66),
Face_xinsui(67),
Face_liwu(69),
Face_taiyang(74),
Face_yueliang(75),
Face_qiang(76),
Face_ruo(77),
Face_woshou(78),
Face_shengli(79),
Face_feiwen(85),
Face_naohuo(86),
Face_xigua(89),
Face_lenghan(96),
Face_cahan(97),
Face_koubi(98),
Face_guzhang(99),
Face_qiudale(100),
Face_huaixiao(101),
Face_zuohengheng(102),
Face_youhengheng(103),
Face_haqian(104),
Face_bishi(105),
Face_weiqu(106),
Face_kuaikule(107),
Face_yinxian(108),
Face_qinqin(109),
Face_xia(110),
Face_kelian(111),
Face_caidao(112),
Face_pijiu(113),
Face_lanqiu(114),
Face_pingpang(115),
Face_shiai(116),
Face_piaochong(117),
Face_baoquan(118),
Face_gouyin(119),
Face_quantou(120),
Face_chajin(121),
Face_aini(122),
Face_bu(123),
Face_hao(124),
Face_zhuanquan(125),
Face_ketou(126),
Face_huitou(127),
Face_tiaosheng(128),
Face_huishou(129),
Face_jidong(130),
Face_jiewu(131),
Face_xianwen(132),
Face_zuotaiji(133),
Face_youtaiji(134),
Face_shuangxi(136),
Face_bianpao(137),
Face_denglong(138),
Face_facai(139),
Face_K_ge(140),
Face_gouwu(141),
Face_youjian(142),
Face_shuai_qi(143),
Face_hecai(144),
Face_qidao(145),
Face_baojin(146),
Face_bangbangtang(147),
Face_he_nai(148),
Face_xiamian(149),
Face_xiangjiao(150),
Face_feiji(151),
Face_kaiche(152),
Face_gaotiezuochetou(153),
Face_chexiang(154),
Face_gaotieyouchetou(155),
Face_duoyun(156),
Face_xiayu(157),
Face_chaopiao(158),
Face_xiongmao(159),
Face_dengpao(160),
Face_fengche(161),
Face_naozhong(162),
Face_dasan(163),
Face_caiqiu(164),
Face_zuanjie(165),
Face_shafa(166),
Face_zhijin(167),
Face_yao(168),
Face_shouqiang(169),
Face_qingwa(170),
// TODO: 2019/9/1 添加更多表情
; ;
...@@ -18,4 +157,15 @@ public enum FaceID { ...@@ -18,4 +157,15 @@ public enum FaceID {
public int getId() { public int getId() {
return id; return id;
} }
public static FaceID ofId(int id) {
for (FaceID value : FaceID.values()) {
if (value.id == id) {
return value;
}
}
return null;
}
} }
...@@ -24,6 +24,10 @@ public abstract class Message { ...@@ -24,6 +24,10 @@ public abstract class Message {
@Override @Override
public abstract String toString(); public abstract String toString();
public String toDebugString() {
return this.getClass().getSimpleName() + String.format("(%s)", this.toString());
}
/** /**
* 把这个消息连接到另一个消息的头部. 相当于字符串相加 * 把这个消息连接到另一个消息的头部. 相当于字符串相加
* <p> * <p>
...@@ -76,4 +80,5 @@ public abstract class Message { ...@@ -76,4 +80,5 @@ public abstract class Message {
this.concat(new At(target)); this.concat(new At(target));
return this; return this;
} }
}
}
\ No newline at end of file
...@@ -21,7 +21,10 @@ public final class Face extends Message { ...@@ -21,7 +21,10 @@ public final class Face extends Message {
@Override @Override
public String toString() { public String toString() {
// TODO: 2019/9/1 if (id == null) {
throw new UnsupportedOperationException(); return "[face?]";
}
return String.format("[face%d]", id.getId());
} }
} }
...@@ -11,6 +11,8 @@ import java.net.URL; ...@@ -11,6 +11,8 @@ import java.net.URL;
* @author Him188moe * @author Him188moe
*/ */
public final class Image extends Message { public final class Image extends Message {
private String imageID;
public Image(InputStream inputStream) { public Image(InputStream inputStream) {
} }
...@@ -33,11 +35,11 @@ public final class Image extends Message { ...@@ -33,11 +35,11 @@ public final class Image extends Message {
* @param imageID * @param imageID
*/ */
public Image(String imageID) { public Image(String imageID) {
this.imageID = imageID;
} }
@Override @Override
public String toString() { public String toString() {
return null; return imageID;
} }
} }
...@@ -29,6 +29,10 @@ public final class MessageChain extends Message { ...@@ -29,6 +29,10 @@ public final class MessageChain extends Message {
list.add(message); list.add(message);
} }
public MessageChain() {
}
/** /**
* @return An unmodifiable list * @return An unmodifiable list
*/ */
...@@ -45,6 +49,10 @@ public final class MessageChain extends Message { ...@@ -45,6 +49,10 @@ public final class MessageChain extends Message {
return this.list.stream().map(Message::toString).collect(Collectors.joining("")); return this.list.stream().map(Message::toString).collect(Collectors.joining(""));
} }
public synchronized String toDebugString() {
return String.format("MessageChain(%s)", this.list.stream().map(Message::toDebugString).collect(Collectors.joining(", ")));
}
@Override @Override
public synchronized Message concat(@NotNull Message tail) { public synchronized Message concat(@NotNull Message tail) {
this.list.add(tail); this.list.add(tail);
......
...@@ -64,6 +64,11 @@ object Protocol { ...@@ -64,6 +64,11 @@ object Protocol {
*/ */
const val key0836 = "EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA" const val key0836 = "EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA"
/**
* 发送/接受消息中的一个const
*/
const val friendMessageConst1 = "00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91"
private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf() private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf()
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
......
...@@ -171,11 +171,10 @@ fun DataOutputStream.writeCRC32(key: ByteArray) { ...@@ -171,11 +171,10 @@ fun DataOutputStream.writeCRC32(key: ByteArray) {
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
@TestedSuccessfully @TestedSuccessfully
fun DataOutputStream.writeDeviceName(random: Boolean = false) { fun DataOutputStream.writeDeviceName(random: Boolean = false) {
val deviceName: String val deviceName: String = if (random) {
if (random) { String(getRandomByteArray(10))
deviceName = String(getRandomByteArray(10))
} else { } else {
deviceName = InetAddress.getLocalHost().hostName InetAddress.getLocalHost().hostName
} }
this.writeShort(deviceName.length + 2) this.writeShort(deviceName.length + 2)
this.writeShort(deviceName.length) this.writeShort(deviceName.length)
......
...@@ -5,10 +5,7 @@ import net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName ...@@ -5,10 +5,7 @@ import net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName
import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.login.*
import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.getAllDeclaredFields
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.toUHexString
import java.io.DataInputStream import java.io.DataInputStream
/** /**
...@@ -66,7 +63,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { ...@@ -66,7 +63,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
} }
return ServerLoginResponseFailedPacket(when (bytes.size) { return ServerLoginResponseFailedPacket(when (bytes.size) {
319, 135 -> LoginState.WRONG_PASSWORD 63, 319, 135, 351 -> LoginState.WRONG_PASSWORD
//135 -> LoginState.RETYPE_PASSWORD //135 -> LoginState.RETYPE_PASSWORD
279 -> LoginState.BLOCKED 279 -> LoginState.BLOCKED
263 -> LoginState.UNKNOWN_QQ_NUMBER 263 -> LoginState.UNKNOWN_QQ_NUMBER
...@@ -77,7 +74,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { ...@@ -77,7 +74,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
/* /*
//unknown //unknown
63 -> throw IllegalArgumentException(bytes.size.toString() + " (Unknown error)") 63 -> throw IllegalArgumentException(bytes.size.toString() + " (Unknown error)")
351 -> throw IllegalArgumentException(bytes.size.toString() + " (Illegal package data or Unknown error)")//包数据有误 351 -> throw IllegalArgumentException(bytes.size.toString() + " (Unknown error)")
else -> throw IllegalArgumentException(bytes.size.toString())*/ else -> throw IllegalArgumentException(bytes.size.toString())*/
}, stream).apply { this.idHex = idHex } }, stream).apply { this.idHex = idHex }
...@@ -183,7 +180,7 @@ fun DataInputStream.readShortVarString(): String { ...@@ -183,7 +180,7 @@ fun DataInputStream.readShortVarString(): String {
return String(this.readNBytes(this.readShort().toInt())) return String(this.readNBytes(this.readShort().toInt()))
} }
fun DataInputStream.readVarString(length: Int): String { fun DataInputStream.readString(length: Int): String {
return String(this.readNBytes(length)) return String(this.readNBytes(length))
} }
...@@ -208,6 +205,17 @@ fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray { ...@@ -208,6 +205,17 @@ fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray {
return this.readNBytes(length.toInt()) return this.readNBytes(length.toInt())
} }
fun DataInputStream.readShortVarNumber(): Number {
return when (this.readShort().toInt()) {
1 -> this.readByte()
2 -> this.readShort()
4 -> this.readInt()
8 -> this.readLong()
else -> throw UnsupportedOperationException()
}
}
fun DataInputStream.readNBytesIn(range: IntRange): ByteArray { fun DataInputStream.readNBytesIn(range: IntRange): ByteArray {
this.goto(range.first) this.goto(range.first)
return this.readNBytes(range.last - range.first + 1) return this.readNBytes(range.last - range.first + 1)
...@@ -218,6 +226,12 @@ fun <N : Number> DataInputStream.readIntAt(position: N): Int { ...@@ -218,6 +226,12 @@ fun <N : Number> DataInputStream.readIntAt(position: N): Int {
return this.readInt(); return this.readInt();
} }
@ExperimentalUnsignedTypes
fun <N : Number> DataInputStream.readUIntAt(position: N): UInt {
this.goto(position)
return this.readNBytes(4).toUInt();
}
fun <N : Number> DataInputStream.readByteAt(position: N): Byte { fun <N : Number> DataInputStream.readByteAt(position: N): Byte {
this.goto(position) this.goto(position)
return this.readByte(); return this.readByte();
......
...@@ -35,7 +35,8 @@ class ClientSendFriendMessagePacket( ...@@ -35,7 +35,8 @@ class ClientSendFriendMessagePacket(
it.writeHex("00 00 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00") it.writeHex("00 00 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00")
it.writeTime() it.writeTime()
it.writeRandom(4) it.writeRandom(4)
it.writeHex("00 00 00 00 09 00 86 00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91") it.writeHex("00 00 00 00 09 00 86")
it.writeHex(Protocol.friendMessageConst1)
it.writeZero(2) it.writeZero(2)
if ("[face" in message if ("[face" in message
......
...@@ -30,7 +30,7 @@ class ClientSendGroupMessagePacket( ...@@ -30,7 +30,7 @@ class ClientSendGroupMessagePacket(
it.writeHex("00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00") it.writeHex("00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00")
it.writeTime() it.writeTime()
it.writeRandom(4) it.writeRandom(4)
it.writeHex("00 00 00 00 09 00 86 00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91") it.writeHex("Protocol.messageConst1")
it.writeZero(2) it.writeZero(2)
//messages //messages
......
...@@ -101,7 +101,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I ...@@ -101,7 +101,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
this.writeHex("00 38")//length this.writeHex("00 38")//length
this.write(token0825)//length this.write(token0825)//length
this.writeHex("03 0F")//tag this.writeHex("03 0F")//tag
this.writeDeviceName(true)//todo 随机 this.writeDeviceName(false)
this.writeHex("00 05 00 06 00 02") this.writeHex("00 05 00 06 00 02")
this.writeQQ(qq) this.writeQQ(qq)
......
...@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol ...@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.ServerPacket import net.mamoe.mirai.network.packet.ServerPacket
import net.mamoe.mirai.network.packet.goto import net.mamoe.mirai.network.packet.goto
import net.mamoe.mirai.network.packet.readNBytesAt import net.mamoe.mirai.network.packet.readNBytesAt
import net.mamoe.mirai.network.packet.readVarString import net.mamoe.mirai.network.packet.readString
import net.mamoe.mirai.utils.TestedSuccessfully import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.toUHexString import net.mamoe.mirai.utils.toUHexString
import java.io.DataInputStream import java.io.DataInputStream
...@@ -43,7 +43,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in ...@@ -43,7 +43,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
this.token88 = this.input.readNBytesAt(189 + msgLength, 136) this.token88 = this.input.readNBytesAt(189 + msgLength, 136)
val nickLength = this.input.goto(624 + msgLength).readByte().toInt() val nickLength = this.input.goto(624 + msgLength).readByte().toInt()
this.nickname = this.input.readVarString(nickLength) this.nickname = this.input.readString(nickLength)
//this.age = this.input.goto(packetDataLength - 28).readShortAt() //this.age = this.input.goto(packetDataLength - 28).readShortAt()
......
...@@ -55,10 +55,11 @@ fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this) ...@@ -55,10 +55,11 @@ fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this) fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() } fun String.hexToInt(): Int = hexToBytes().toUInt().toInt()
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun String.hexToInt(): Int = hexToBytes().let { ((it[0].toInt() shl 24) + (it[1].toInt() shl 16) + (it[2].toInt() shl 8) + it[3]) } fun ByteArray.toUInt(): UInt =
this[0].toUInt().and(255u).shl(24) + this[1].toUInt().and(255u).shl(16) + this[2].toUInt().and(255u).shl(8) + this[3].toUInt().and(255u).shl(0)
open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) { open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray() open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
......
...@@ -50,10 +50,20 @@ public class HexComparator { ...@@ -50,10 +50,20 @@ public class HexComparator {
@SuppressWarnings({"unused", "NonAsciiCharacters"}) @SuppressWarnings({"unused", "NonAsciiCharacters"})
private static class TestConsts { private static class TestConsts {
private static final String 牛逼 = UtilsKt.toUHexString("牛逼".getBytes(), " "); private static final String NIU_BI = UtilsKt.toUHexString("牛逼".getBytes(), " ");
private static final String _1994701021 = ClientPacketKt.toUHexString(1994701021, " "); private static final String _1994701021 = ClientPacketKt.toUHexString(1994701021, " ");
private static final String _1040400290 = ClientPacketKt.toUHexString(1040400290, " "); private static final String _1040400290 = ClientPacketKt.toUHexString(1040400290, " ");
private static final String _580266363 = ClientPacketKt.toUHexString(580266363, " "); private static final String _580266363 = ClientPacketKt.toUHexString(580266363, " ");
private static final String _1040400290_ = "3E 03 3F A2";
private static final String _1994701021_ = "76 E4 B8 DD";
private static final String _jiahua_ = "B1 89 BE 09";
private static final String SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01";
private static final String MESSAGE_TAIL_10404 = "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".replace(" ", " ");
//private static final String MESSAGE_TAIL2_10404 ="".replace(" ", " ");
} }
private final List<Match> matches = new LinkedList<>(); private final List<Match> matches = new LinkedList<>();
...@@ -88,7 +98,7 @@ public class HexComparator { ...@@ -88,7 +98,7 @@ public class HexComparator {
return new LinkedList<>(); return new LinkedList<>();
} }
return new LinkedList<>() {{ return new LinkedList<>() {{
int index = 0; int index = -1;
while ((index = hex.indexOf(constValue, index + 1)) != -1) { while ((index = hex.indexOf(constValue, index + 1)) != -1) {
add(new IntRange(index / 3, (index + constValue.length()) / 3)); add(new IntRange(index / 3, (index + constValue.length()) / 3));
} }
...@@ -105,18 +115,20 @@ public class HexComparator { ...@@ -105,18 +115,20 @@ public class HexComparator {
} }
private static void buildConstNameChain(int length, ConstMatcher constMatcher, StringBuilder constNameBuilder) { private static void buildConstNameChain(int length, ConstMatcher constMatcher, StringBuilder constNameBuilder) {
//System.out.println(constMatcher.matches);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
constNameBuilder.append(" "); constNameBuilder.append(" ");
String match = constMatcher.getMatchedConstName(i / 4); String match = constMatcher.getMatchedConstName(i / 4);
if (match != null) { if (match != null) {
int appendedNameLength = match.length(); int appendedNameLength = match.length();
constNameBuilder.append(match); constNameBuilder.append(match);
while (constMatcher.getMatchedConstName(i++ / 4) != null) { while (match.equals(constMatcher.getMatchedConstName(i++ / 4))) {
if (appendedNameLength-- <= 0) { if (appendedNameLength-- < 0) {
constNameBuilder.append(" "); constNameBuilder.append(" ");
} }
} }
constNameBuilder.append(" ".repeat(match.length() % 4));
} }
} }
} }
...@@ -281,10 +293,10 @@ public class HexComparator { ...@@ -281,10 +293,10 @@ public class HexComparator {
System.out.println(HexComparator.compare( System.out.println(HexComparator.compare(
//mirai //mirai
"2A 22 96 29 7B 00 40 00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 EC 21 40 06 18 89 54 BC 00 00 00 00 09 00 86 00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 0A 01 00 07 E7 89 9B E9 80 BC 21\n" "2A 22 96 29 7B 00 40 00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 EC 21 40 06 18 89 54 BC Protocol.messageConst1 00 00 01 00 0A 01 00 07 E7 89 9B E9 80 BC 21\n"
, ,
//e //e
"2A 22 96 29 7B 00 3F 00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 6B 8E 1A FE 39 0B FC 00 00 00 00 09 00 86 00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 0A 01 00 07 6D 65 73 73 61 67 65" "2A 22 96 29 7B 00 3F 00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 6B 8E 1A FE 39 0B FC Protocol.messageConst1 00 00 01 00 0A 01 00 07 6D 65 73 73 61 67 65"
)); ));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment