Commit 9fda59af authored by Him188moe's avatar Him188moe

Message analysis

parent 21a0df80
......@@ -4,8 +4,147 @@ package net.mamoe.mirai.message;
* @author Him188moe
*/
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 {
public int getId() {
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 {
@Override
public abstract String toString();
public String toDebugString() {
return this.getClass().getSimpleName() + String.format("(%s)", this.toString());
}
/**
* 把这个消息连接到另一个消息的头部. 相当于字符串相加
* <p>
......@@ -76,4 +80,5 @@ public abstract class Message {
this.concat(new At(target));
return this;
}
}
}
\ No newline at end of file
......@@ -21,7 +21,10 @@ public final class Face extends Message {
@Override
public String toString() {
// TODO: 2019/9/1
throw new UnsupportedOperationException();
if (id == null) {
return "[face?]";
}
return String.format("[face%d]", id.getId());
}
}
......@@ -11,6 +11,8 @@ import java.net.URL;
* @author Him188moe
*/
public final class Image extends Message {
private String imageID;
public Image(InputStream inputStream) {
}
......@@ -33,11 +35,11 @@ public final class Image extends Message {
* @param imageID
*/
public Image(String imageID) {
this.imageID = imageID;
}
@Override
public String toString() {
return null;
return imageID;
}
}
......@@ -29,6 +29,10 @@ public final class MessageChain extends Message {
list.add(message);
}
public MessageChain() {
}
/**
* @return An unmodifiable list
*/
......@@ -45,6 +49,10 @@ public final class MessageChain extends Message {
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
public synchronized Message concat(@NotNull Message tail) {
this.list.add(tail);
......
......@@ -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
*/
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()
@ExperimentalUnsignedTypes
......
......@@ -171,11 +171,10 @@ fun DataOutputStream.writeCRC32(key: ByteArray) {
@ExperimentalUnsignedTypes
@TestedSuccessfully
fun DataOutputStream.writeDeviceName(random: Boolean = false) {
val deviceName: String
if (random) {
deviceName = String(getRandomByteArray(10))
val deviceName: String = if (random) {
String(getRandomByteArray(10))
} else {
deviceName = InetAddress.getLocalHost().hostName
InetAddress.getLocalHost().hostName
}
this.writeShort(deviceName.length + 2)
this.writeShort(deviceName.length)
......
......@@ -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.ServerSendGroupMessageResponsePacket
import net.mamoe.mirai.network.packet.login.*
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.getAllDeclaredFields
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.toUHexString
import net.mamoe.mirai.utils.*
import java.io.DataInputStream
/**
......@@ -66,7 +63,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
return ServerLoginResponseFailedPacket(when (bytes.size) {
319, 135 -> LoginState.WRONG_PASSWORD
63, 319, 135, 351 -> LoginState.WRONG_PASSWORD
//135 -> LoginState.RETYPE_PASSWORD
279 -> LoginState.BLOCKED
263 -> LoginState.UNKNOWN_QQ_NUMBER
......@@ -77,7 +74,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
/*
//unknown
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())*/
}, stream).apply { this.idHex = idHex }
......@@ -183,7 +180,7 @@ fun DataInputStream.readShortVarString(): String {
return String(this.readNBytes(this.readShort().toInt()))
}
fun DataInputStream.readVarString(length: Int): String {
fun DataInputStream.readString(length: Int): String {
return String(this.readNBytes(length))
}
......@@ -208,6 +205,17 @@ fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray {
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 {
this.goto(range.first)
return this.readNBytes(range.last - range.first + 1)
......@@ -218,6 +226,12 @@ fun <N : Number> DataInputStream.readIntAt(position: N): Int {
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 {
this.goto(position)
return this.readByte();
......
......@@ -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.writeTime()
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)
if ("[face" in message
......
......@@ -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.writeTime()
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)
//messages
......
......@@ -101,7 +101,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
this.writeHex("00 38")//length
this.write(token0825)//length
this.writeHex("03 0F")//tag
this.writeDeviceName(true)//todo 随机
this.writeDeviceName(false)
this.writeHex("00 05 00 06 00 02")
this.writeQQ(qq)
......
......@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.ServerPacket
import net.mamoe.mirai.network.packet.goto
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.toUHexString
import java.io.DataInputStream
......@@ -43,7 +43,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
this.token88 = this.input.readNBytesAt(189 + msgLength, 136)
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()
......
......@@ -55,10 +55,11 @@ fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
@ExperimentalUnsignedTypes
fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() }
fun String.hexToInt(): Int = hexToBytes().toUInt().toInt()
@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 fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
......
......@@ -50,10 +50,20 @@ public class HexComparator {
@SuppressWarnings({"unused", "NonAsciiCharacters"})
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 _1040400290 = ClientPacketKt.toUHexString(1040400290, " ");
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<>();
......@@ -88,7 +98,7 @@ public class HexComparator {
return new LinkedList<>();
}
return new LinkedList<>() {{
int index = 0;
int index = -1;
while ((index = hex.indexOf(constValue, index + 1)) != -1) {
add(new IntRange(index / 3, (index + constValue.length()) / 3));
}
......@@ -105,18 +115,20 @@ public class HexComparator {
}
private static void buildConstNameChain(int length, ConstMatcher constMatcher, StringBuilder constNameBuilder) {
//System.out.println(constMatcher.matches);
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) {
while (match.equals(constMatcher.getMatchedConstName(i++ / 4))) {
if (appendedNameLength-- < 0) {
constNameBuilder.append(" ");
}
}
constNameBuilder.append(" ".repeat(match.length() % 4));
}
}
}
......@@ -281,10 +293,10 @@ public class HexComparator {
System.out.println(HexComparator.compare(
//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
"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