Commit 8b5479f5 authored by liujiahua123123's avatar liujiahua123123

Merge branch 'master' of https://github.com/mamoe/mirai

parents 4a7b706f 31bb236e
...@@ -30,5 +30,4 @@ mirai.iml ...@@ -30,5 +30,4 @@ mirai.iml
.idea/* .idea/*
/.idea/* /.idea/*
test/
/test /test
\ No newline at end of file
...@@ -21,21 +21,10 @@ ...@@ -21,21 +21,10 @@
</parent> </parent>
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
<dependency> <dependency>
<groupId>org.apache.mina</groupId> <groupId>org.jetbrains.kotlinx</groupId>
<artifactId>mina-core</artifactId> <artifactId>kotlinx-coroutines-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-ssl -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-filter-ssl</artifactId>
<version>1.1.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-compression -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-filter-compression</artifactId>
<version>2.1.3</version>
</dependency> </dependency>
<dependency> <dependency>
......
...@@ -128,7 +128,7 @@ public class MiraiServer { ...@@ -128,7 +128,7 @@ public class MiraiServer {
MiraiConfigSection<MiraiConfigSection> x = this.qqs.getTypedSection("test"); MiraiConfigSection<MiraiConfigSection> x = this.qqs.getTypedSection("test");
System.out.println(x.getSection("1").getInt("1")); //System.out.println(x.getSection("1").getInt("1"));
/* /*
System.out.println(v); System.out.println(v);
...@@ -136,7 +136,6 @@ public class MiraiServer { ...@@ -136,7 +136,6 @@ public class MiraiServer {
System.out.println(v.get("1111")); System.out.println(v.get("1111"));
*/ */
System.exit(0);
Robot robot = new Robot(1994701021, "xiaoqqq"); Robot robot = new Robot(1994701021, "xiaoqqq");
try { try {
......
...@@ -22,4 +22,12 @@ class QQ(number: Int) : Contact(number) { ...@@ -22,4 +22,12 @@ class QQ(number: Int) : Contact(number) {
fun at(): String { fun at(): String {
return "[@$number]" return "[@$number]"
} }
/*
Make that we can use (QQ + QQ2 + QQ3).sendMessage( )
operator fun plus(qq: QQ): QQCombination {
}*/
} }
package net.mamoe.mirai.network;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.DatagramSessionConfig;
import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
import java.io.IOException;
import java.net.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class MemoryMonitorTest {
private static final long serialVersionUID = 1L;
public static final int PORT = 8080;
public MemoryMonitorTest() throws IOException {
NioDatagramAcceptor acceptor = new NioDatagramAcceptor();//创建一个UDP的接收器
acceptor.setHandler(new YourHandler());//设置接收器的处理程序
Executor threadPool = Executors.newFixedThreadPool(1500);//建立线程池
acceptor.getFilterChain().addLast("exector", new ExecutorFilter(threadPool));
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
DatagramSessionConfig dcfg = acceptor.getSessionConfig();//建立连接的配置文件
dcfg.setReadBufferSize(4096);//设置接收最大字节默认2048
dcfg.setReceiveBufferSize(1024);//设置输入缓冲区的大小
dcfg.setSendBufferSize(1024);//设置输出缓冲区的大小
dcfg.setReuseAddress(true);//设置每一个非主监听连接的端口可以重用
acceptor.bind(new InetSocketAddress(PORT));//绑定端口
}
public static void main(String[] args) throws IOException {
new MemoryMonitorTest();
}
public class YourHandler extends IoHandlerAdapter {
//messageSent是Server响应给Clinet成功后触发的事件
@Override
public void messageSent(IoSession session, Object message) throws Exception {
if (message instanceof IoBuffer) {
IoBuffer buffer = (IoBuffer) message;
byte[] bb = buffer.array();
for (int i = 0; i < bb.length; i++) {
System.out.print((char) bb[i]);
}
}
}
//抛出异常触发的事件
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
session.close(true);
}
//Server接收到UDP请求触发的事件
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
System.out.println("messageReceived");
if (message instanceof IoBuffer) {
IoBuffer buffer = (IoBuffer) message;
// byte[] bb = buffer.array();
// for(int i=0;i<bb.length;i++) {
// System.out.print((char)bb[i]);
// }
IoBuffer buffer1 = IoBuffer.wrap("11".getBytes());//返回信息给Clinet端
session.write(buffer1);
//声明这里message必须为IoBuffer类型
}
}
//连接关闭触发的事件
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("Session closed...");
}
//建立连接触发的事件
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("Session created...");
SocketAddress remoteAddress = session.getRemoteAddress();
System.out.println(remoteAddress);
}
//会话空闲
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println("Session idle...");
}
//打开连接触发的事件,它与sessionCreated的区别在于,一个连接地址(A)第一次请求Server会建立一个Session默认超时时间为1分钟,此时若未达到超时时间这个连接地址(A)再一次向Server发送请求即是sessionOpened(连接地址(A)第一次向Server发送请求或者连接超时后向Server发送请求时会同时触发sessionCreated和sessionOpened两个事件)
@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("Session Opened...");
SocketAddress remoteAddress = session.getRemoteAddress();
System.out.println(remoteAddress);
}
public void send(String host, int port) {
try {
InetAddress ia = InetAddress.getByName(host);
DatagramSocket socket = new DatagramSocket(9999);
socket.connect(ia, port);
byte[] buffer = new byte[1024];
buffer = ("22")
.getBytes();
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
System.out.println(dp.getLength());
DatagramPacket dp1 = new DatagramPacket(new byte[22312], 22312);
socket.send(dp);
socket.receive(dp1);
byte[] bb = dp1.getData();
for (int i = 0; i < dp1.getLength(); i++) {
System.out.print((char) bb[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
...@@ -68,9 +68,9 @@ class Robot(val number: Int, private val password: String) { ...@@ -68,9 +68,9 @@ class Robot(val number: Int, private val password: String) {
} else {//password submission } else {//password submission
this.loginIP = packet.loginIP this.loginIP = packet.loginIP
this.loginTime = packet.loginTime this.loginTime = packet.loginTime
this.token0825 = packet.token this.token0825 = packet.token0825
this.tgtgtKey = packet.tgtgtKey this.tgtgtKey = packet.tgtgtKey
sendPacket(ClientPasswordSubmissionPacket(this.number, this.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token)) sendPacket(ClientPasswordSubmissionPacket(this.number, this.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token0825))
} }
} }
...@@ -81,7 +81,7 @@ class Robot(val number: Int, private val password: String) { ...@@ -81,7 +81,7 @@ class Robot(val number: Int, private val password: String) {
} }
is ServerLoginResponseVerificationCodePacket -> { is ServerLoginResponseVerificationCodePacket -> {
//[token00BA]可能来自这里 //[token00BA]来源之一: 验证码
this.token00BA = packet.token00BA this.token00BA = packet.token00BA
if (packet.unknownBoolean != null && packet.unknownBoolean!!) { if (packet.unknownBoolean != null && packet.unknownBoolean!!) {
this.sequence = 1 this.sequence = 1
...@@ -95,13 +95,17 @@ class Robot(val number: Int, private val password: String) { ...@@ -95,13 +95,17 @@ class Robot(val number: Int, private val password: String) {
sendPacket(ClientLoginSucceedConfirmationPacket(this.number, this.serverIP, this.loginIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105)) sendPacket(ClientLoginSucceedConfirmationPacket(this.number, this.serverIP, this.loginIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105))
} }
//这个有可能是客户端发送验证码之后收到的回复验证码是否正确? //是ClientPasswordSubmissionPacket之后服务器回复的
is ServerLoginResponseResendPacket -> { is ServerLoginResponseResendPacket -> {
if (packet.token00BA != null) {
this.token00BA = packet.token00BA!!
println(token00BA)
}
if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) { if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) {
this.tgtgtKey = packet.tgtgtKey this.tgtgtKey = packet.tgtgtKey
sendPacket(ClientLoginResendPacket3104(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA)) sendPacket(ClientLoginResendPacket3104(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA, packet._0836_tlv0006_encr))
} else { } else {
sendPacket(ClientLoginResendPacket3106(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA)) sendPacket(ClientLoginResendPacket3106(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA, packet._0836_tlv0006_encr))
} }
} }
...@@ -129,28 +133,27 @@ class Robot(val number: Int, private val password: String) { ...@@ -129,28 +133,27 @@ class Robot(val number: Int, private val password: String) {
e.printStackTrace() e.printStackTrace()
} }
packet.writeHex(Protocol.tail) packet.writeHex(Protocol.tail)
println(packet)
println(packet.toByteArray().toUByteArray().toHexString())
/*val p = DatagramPacket(packet.toByteArray()); /*val p = DatagramPacket(packet.toByteArray());
p.socketAddress = this.serverAddress*/ p.socketAddress = this.serverAddress*/
//ctx.writeAndFlush(packet.toByteArray()).sync() //ctx.writeAndFlush(packet.toByteArray()).sync()
send(packet.toByteArray()) MiraiLogger info "Sending: $packet"
//GlobalScope.launch {
send(packet.toByteArray())
//}
//println(channel!!.writeAndFlush(packet.toByteArray()).channel().connect(serverAddress).sync().get()) //println(channel!!.writeAndFlush(packet.toByteArray()).channel().connect(serverAddress).sync().get())
MiraiLogger info "Packet sent: $packet"
} }
private fun DatagramPacket(toByteArray: ByteArray): DatagramPacket = DatagramPacket(toByteArray, toByteArray.size, this.serverAddress)
// private val socket = DatagramSocket(15314) // private val socket = DatagramSocket(15314)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun send(data: ByteArray) { fun send(data: ByteArray) {
try { try {
val socket = DatagramSocket((15314 + Math.random() * 5).toInt()) val socket = DatagramSocket((15314 + Math.random() * 10).toInt())
socket.connect(this.serverAddress) socket.connect(this.serverAddress)
val dp1 = DatagramPacket(ByteArray(22312), 22312) val dp1 = DatagramPacket(ByteArray(22312), 22312)
socket.send(DatagramPacket(data, data.size)) socket.send(DatagramPacket(data, data.size))
MiraiLogger info "Packet sent: ${data.toUByteArray().toHexString()}"
socket.receive(dp1) socket.receive(dp1)
val zeroByte: Byte = 0 val zeroByte: Byte = 0
var i = dp1.data.size - 1; var i = dp1.data.size - 1;
......
...@@ -41,7 +41,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet { ...@@ -41,7 +41,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
* Encode this packet. * Encode this packet.
* *
* *
* Before sending the packet, an [tail][Protocol.tail] will be added. * Before sending the packet, a [tail][Protocol.tail] will be added.
*/ */
@Throws(IOException::class) @Throws(IOException::class)
abstract fun encode() abstract fun encode()
...@@ -53,11 +53,12 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet { ...@@ -53,11 +53,12 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
} }
override fun toString(): String { override fun toString(): String {
return this.javaClass.simpleName + this.javaClass.declaredFields.joinToString(", ", "{", "}") { it.trySetAccessible(); it.name + "=" + it.get(this) } return this.javaClass.simpleName + this.getAllDeclaredFields().joinToString(", ", "{", "}") { it.trySetAccessible(); it.name + "=" + it.get(this) }
} }
} }
@ExperimentalUnsignedTypes
@Throws(IOException::class) @Throws(IOException::class)
fun DataOutputStream.writeIP(ip: String) { fun DataOutputStream.writeIP(ip: String) {
for (s in ip.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { for (s in ip.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
...@@ -99,6 +100,22 @@ fun DataOutputStream.writeVarInt(dec: UInt) { ...@@ -99,6 +100,22 @@ fun DataOutputStream.writeVarInt(dec: UInt) {
throw UnsupportedOperationException() throw UnsupportedOperationException()
} }
fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
this.write(TEACryptor.encrypt(byteArray, key))
}
fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, cryptor: TEACryptor) {
this.write(cryptor.encrypt(byteArray))
}
fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutputStream) -> Unit) {
this.write(TEACryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }, key))
}
fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: (ByteArrayDataOutputStream) -> Unit) {
this.write(cryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }))
}
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
@Throws(IOException::class) @Throws(IOException::class)
fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) { fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) {
...@@ -111,40 +128,67 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log ...@@ -111,40 +128,67 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
val md5_1 = md5(password); 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.toByteArray())
println(md5_1.toUByteArray().toHexString())
println(md5_2.toUByteArray().toHexString())
it.write(md5_1) it.write(md5_1)
it.writeInt(loginTime)//todo FIXED 12(maybe 11???) bytes??? check that it.writeInt(loginTime)
it.writeByte(0); it.writeByte(0);
it.writeZero(4 * 3) it.writeZero(4 * 3)
it.writeIP(loginIP) it.writeIP(loginIP)
it.writeZero(8)
it.writeHex("00 10") it.writeHex("00 10")
it.writeHex("15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B") it.writeHex("15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B")
it.write(tgtgtKey) it.write(tgtgtKey)
this.write(TEACryptor.encrypt(md5_2, it.toByteArray())) println()
println(it.toByteArray().toUHexString())
this.write(TEACryptor.encrypt(it.toByteArray(), md5_2))
} }
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32() { fun main() {
getRandomKey(16).let { println(lazyEncode { it.writeTLV0006(1994701021, "D1 A5 C8 BB E1 Q3 CC DD", 131513, "123.123.123.123", "AA BB CC DD EE FF AA BB CC".hexToBytes()) }.toUByteArray().toHexString())
}
@ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32() = writeCRC32(getRandomKey(16))
@ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32(key: ByteArray) {
key.let {
write(it)//key write(it)//key
writeLong(getCrc32(it))//todo may be int? check that. writeInt(getCrc32(it))
} }
} }
fun DataOutputStream.writeHostname() { fun DataOutputStream.writeDeviceName() {
val hostName: String = InetAddress.getLocalHost().hostName.let { it.substring(0, it.length - 3) }; val deviceName = InetAddress.getLocalHost().hostName
this.writeShort(hostName.length / 2);//todo check that this.writeShort(deviceName.length + 2)
this.writeShort(hostName.length); this.writeShort(deviceName.length)
this.writeBytes(hostName)//todo 这个对吗? this.writeBytes(deviceName)
} }
fun Int.toByteArray(): ByteArray = byteArrayOf(//todo 检查这方法对不对, 这其实就是从 DataInputStream copy来的 /**
* 255 -> 00 00 00 FF
*/
fun Int.toByteArray(): ByteArray = byteArrayOf(
(this.ushr(24) and 0xFF).toByte(), (this.ushr(24) and 0xFF).toByte(),
(this.ushr(16) and 0xFF).toByte(), (this.ushr(16) and 0xFF).toByte(),
(this.ushr(8) and 0xFF).toByte(), (this.ushr(8) and 0xFF).toByte(),
(this.ushr(0) and 0xFF).toByte() (this.ushr(0) and 0xFF).toByte()
) )
/**
* 255 -> FF 00 00 00
*/
fun Int.toLByteArray(): ByteArray = byteArrayOf(
(this.ushr(0) and 0xFF).toByte(),
(this.ushr(8) and 0xFF).toByte(),
(this.ushr(16) and 0xFF).toByte(),
(this.ushr(24) and 0xFF).toByte()
)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toHexString(separator); fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toHexString(separator);
...@@ -155,14 +199,14 @@ private fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD ...@@ -155,14 +199,14 @@ private fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
@Throws(IOException::class) @Throws(IOException::class)
fun DataOutputStream.writeZero(count: Int) { fun DataOutputStream.writeZero(count: Int) {
for (x in 0..count) { repeat(count) {
this.writeByte(0) this.writeByte(0)
} }
} }
@Throws(IOException::class) @Throws(IOException::class)
fun DataOutputStream.writeRandom(length: Int) { fun DataOutputStream.writeRandom(length: Int) {
for (i in 0 until length) { repeat(length) {
this.writeByte((Math.random() * 255).toInt().toByte().toInt()) this.writeByte((Math.random() * 255).toInt().toByte().toInt())
} }
} }
......
...@@ -3,10 +3,9 @@ package net.mamoe.mirai.network.packet.client.login ...@@ -3,10 +3,9 @@ package net.mamoe.mirai.network.packet.client.login
import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.client.* import net.mamoe.mirai.network.packet.client.*
import net.mamoe.mirai.util.ByteArrayDataOutputStream import net.mamoe.mirai.util.*
import net.mamoe.mirai.util.TEACryptor import java.io.DataOutputStream
import net.mamoe.mirai.util.getRandomKey import java.net.InetAddress
import net.mamoe.mirai.util.hexToBytes
/** /**
* Password submission (0836_622) * Password submission (0836_622)
...@@ -15,7 +14,14 @@ import net.mamoe.mirai.util.hexToBytes ...@@ -15,7 +14,14 @@ import net.mamoe.mirai.util.hexToBytes
*/ */
@PacketId("08 36 31 03") @PacketId("08 36 31 03")
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() { class ClientPasswordSubmissionPacket(
private val qq: Int,
private val password: String,
private val loginTime: Int,
private val loginIP: String,
private val tgtgtKey: ByteArray,
private val token0825: ByteArray
) : ClientPacket() {
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
override fun encode() { override fun encode() {
this.writeQQ(qq) this.writeQQ(qq)
...@@ -24,26 +30,24 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password: ...@@ -24,26 +30,24 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password:
this.writeHex("00 00 00 10") this.writeHex("00 00 00 10")
this.writeHex(Protocol._0836key1) this.writeHex(Protocol._0836key1)
this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() { this.encryptAndWrite(Protocol.shareKey.hexToBytes()) {
override fun toByteArray(): ByteArray { it.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825) it.writePart2()
writePart2() println(it.toByteArray().toUHexString())
return super.toByteArray() }
}
}.toByteArray(), Protocol.shareKey.hexToBytes()))
} }
} }
@PacketId("08 36 31 04") @PacketId("08 36 31 04")
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class ClientLoginResendPacket3104(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA) class ClientLoginResendPacket3104(qq: Int, 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 06") @PacketId("08 36 31 06")
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class ClientLoginResendPacket3106(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA) class ClientLoginResendPacket3106(qq: Int, 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 @ExperimentalUnsignedTypes
open class ClientLoginResendPacket internal constructor(val qq: Int, val password: String, val loginTime: Int, val loginIP: String, val tgtgtKey: ByteArray, val token0825: ByteArray, val token00BA: ByteArray) : ClientPacket() { open class ClientLoginResendPacket internal constructor(val qq: Int, val password: String, val loginTime: Int, val loginIP: String, val tgtgtKey: ByteArray, val token0825: ByteArray, val token00BA: ByteArray, val tlv_0006_encr: ByteArray? = null) : ClientPacket() {
override fun encode() { override fun encode() {
this.writeQQ(qq) this.writeQQ(qq)
this.writeHex(Protocol._0836_622_fix1) this.writeHex(Protocol._0836_622_fix1)
...@@ -53,7 +57,7 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor ...@@ -53,7 +57,7 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor
this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() { this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
override fun toByteArray(): ByteArray { override fun toByteArray(): ByteArray {
writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825) this.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825, tlv_0006_encr)
this.writeHex("01 10") //tag this.writeHex("01 10") //tag
this.writeHex("00 3C")//length this.writeHex("00 3C")//length
...@@ -61,13 +65,17 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor ...@@ -61,13 +65,17 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor
this.writeHex("00 38")//length this.writeHex("00 38")//length
this.write(token00BA)//value this.write(token00BA)//value
writePart2() this.writePart2()
return super.toByteArray() return super.toByteArray()
} }
}.toByteArray(), Protocol.shareKey.hexToBytes())) }.toByteArray(), Protocol.shareKey.hexToBytes()))
} }
} }
fun main() {
println(InetAddress.getLocalHost().hostAddress)
}
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
@PacketId("08 28 04 34") @PacketId("08 28 04 34")
class ClientLoginSucceedConfirmationPacket( class ClientLoginSucceedConfirmationPacket(
...@@ -112,7 +120,7 @@ class ClientLoginSucceedConfirmationPacket( ...@@ -112,7 +120,7 @@ class ClientLoginSucceedConfirmationPacket(
this.writeHex("68") this.writeHex("68")
this.writeHex("00 00 00 00 00 2D 00 06 00 01") this.writeHex("00 00 00 00 00 2D 00 06 00 01")
this.writeIP(loginIP)//本地IP地址? todo test that this.writeIP(InetAddress.getLocalHost().hostName)//? todo 这随便扔的
return super.toByteArray() return super.toByteArray()
} }
...@@ -124,14 +132,14 @@ class ClientLoginSucceedConfirmationPacket( ...@@ -124,14 +132,14 @@ class ClientLoginSucceedConfirmationPacket(
* @author Him188moe * @author Him188moe
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray) { private fun DataOutputStream.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv_0006_encr: ByteArray? = null) {
this.writeQQ(System.currentTimeMillis().toInt())//that's correct //this.writeInt(System.currentTimeMillis().toInt())
this.writeHex("01 12")//tag this.writeHex("01 12")//tag
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.writeHostname()//todo 务必检查这个 this.writeDeviceName()
/*易语言源码: PCName就是HostName /*易语言源码: PCName就是HostName
PCName = BytesToStr (Ansi转Utf8 (取主机名 ())) PCName = BytesToStr (Ansi转Utf8 (取主机名 ()))
PCName = 取文本左边 (PCName, 取文本长度 (PCName) - 3)*/ PCName = 取文本左边 (PCName, 取文本长度 (PCName) - 3)*/
...@@ -140,7 +148,11 @@ private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, l ...@@ -140,7 +148,11 @@ private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, l
this.writeQQ(qq) this.writeQQ(qq)
this.writeHex("00 06")//tag this.writeHex("00 06")//tag
this.writeHex("00 78")//length this.writeHex("00 78")//length
this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey) if (tlv_0006_encr != null) {
this.write(tlv_0006_encr)
} else {
this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey)
}
//fix //fix
this.writeHex(Protocol._0836_622_fix2) this.writeHex(Protocol._0836_622_fix2)
this.writeHex("00 1A")//tag this.writeHex("00 1A")//tag
...@@ -160,7 +172,7 @@ private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, l ...@@ -160,7 +172,7 @@ private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, l
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
private fun ClientPacket.writePart2() { private fun DataOutputStream.writePart2() {
this.writeHex("03 12")//tag this.writeHex("03 12")//tag
this.writeHex("00 05")//length this.writeHex("00 05")//length
......
...@@ -18,7 +18,7 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : ...@@ -18,7 +18,7 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) :
} }
lateinit var _0836_tlv0006_encr: ByteArray; lateinit var _0836_tlv0006_encr: ByteArray;
lateinit var token: ByteArray var token00BA: ByteArray? = null
lateinit var tgtgtKey: ByteArray lateinit var tgtgtKey: ByteArray
override fun decode() { override fun decode() {
...@@ -29,7 +29,7 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : ...@@ -29,7 +29,7 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) :
when (flag) { when (flag) {
Flag.`08 36 31 03` -> { Flag.`08 36 31 03` -> {
token = this.input.goto(153).readNBytes(56) token00BA = this.input.goto(153).readNBytes(56)
} }
Flag.OTHER -> { Flag.OTHER -> {
......
package net.mamoe.mirai.network.packet.server.login package net.mamoe.mirai.network.packet.server.login
import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.server.* import net.mamoe.mirai.network.packet.server.ServerPacket
import net.mamoe.mirai.network.packet.server.goto
import net.mamoe.mirai.network.packet.server.readNBytes
import net.mamoe.mirai.network.packet.server.readVarString
import net.mamoe.mirai.util.TEACryptor import net.mamoe.mirai.util.TEACryptor
import net.mamoe.mirai.util.hexToBytes import net.mamoe.mirai.util.hexToBytes
import net.mamoe.mirai.util.toHexString import net.mamoe.mirai.util.toHexString
...@@ -39,11 +42,11 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream, val packetDataLen ...@@ -39,11 +42,11 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream, val packetDataLen
//?? //??
var b = this.input.readNBytes(2) var b = this.input.readNBytes(2)
val msgLength = when (b.toUByteArray().toHexString()) { val msgLength = when (b.toUByteArray().toHexString()) {
"01 07" -> 0 "01 07" -> 0
"00 33" -> 28 "00 33" -> 28
"01 10" -> 65 "01 10" -> 65
else -> throw IllegalStateException() else -> throw IllegalStateException()
}//144 }//144
System.out.println(msgLength) System.out.println(msgLength)
...@@ -96,16 +99,16 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream, val packetDataLen ...@@ -96,16 +99,16 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream, val packetDataLen
this.token38 = this.input.readNBytes(56)//82 this.token38 = this.input.readNBytes(56)//82
this.input.skip(60L)//142 this.input.skip(60L)//142
val msgLength = when (this.input.readNBytes(2).toUByteArray().toHexString()) { val msgLength = when (val id = this.input.readNBytes(2).toUByteArray().toHexString()) {
"01 07" -> 0 "01 07" -> 0
"00 33" -> 28 "00 33" -> 28
"01 10" -> 64 "01 10" -> 64
else -> throw IllegalStateException() else -> throw IllegalStateException(id)
} }
this._0828_rec_decr_key = this.input.readNBytes(171 + msgLength,16) this._0828_rec_decr_key = this.input.readNBytes(171 + msgLength, 16)
this.token88 = this.input.readNBytes(189 + msgLength,136) this.token88 = this.input.readNBytes(189 + msgLength, 136)
val nickLength = this.input.goto(624 + msgLength).readByte().toInt() val nickLength = this.input.goto(624 + msgLength).readByte().toInt()
this.nick = this.input.readVarString(nickLength) this.nick = this.input.readVarString(nickLength)
...@@ -123,8 +126,12 @@ class ServerLoginResponseSuccessPacketEncrypted(input: DataInputStream, val leng ...@@ -123,8 +126,12 @@ class ServerLoginResponseSuccessPacketEncrypted(input: DataInputStream, val leng
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket {//todo test fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket {//todo test
this.input.skip(7) input.skip(7)
return ServerLoginResponseSuccessPacket(TEACryptor.decrypt(TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, Protocol.shareKey.hexToBytes()), tgtgtKey).dataInputStream(), length); var bytes = input.readAllBytes();
bytes = bytes.copyOfRange(0, bytes.size - 1);
println(bytes.toUByteArray().toHexString())
return ServerLoginResponseSuccessPacket(DataInputStream(TEACryptor.decrypt(bytes, Protocol.shareKey.hexToBytes()).inputStream()), length);
//TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key) //TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
} }
} }
package net.mamoe.mirai.network.packet.server.touch package net.mamoe.mirai.network.packet.server.touch
import lombok.ToString
import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.server.ServerPacket import net.mamoe.mirai.network.packet.server.ServerPacket
import net.mamoe.mirai.network.packet.server.readIP import net.mamoe.mirai.network.packet.server.readIP
...@@ -18,13 +17,12 @@ import java.io.DataInputStream ...@@ -18,13 +17,12 @@ import java.io.DataInputStream
* *
* @author Him188moe * @author Him188moe
*/ */
@ToString
class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) { class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
var serverIP: String? = null; var serverIP: String? = null;
var loginTime: Int = 0 var loginTime: Int = 0
lateinit var loginIP: String lateinit var loginIP: String
lateinit var token: ByteArray lateinit var token0825: ByteArray
lateinit var tgtgtKey: ByteArray lateinit var tgtgtKey: ByteArray
enum class Type { enum class Type {
...@@ -41,7 +39,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp ...@@ -41,7 +39,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
} }
0x00 -> { 0x00 -> {
input.skip(4) input.skip(4)
token = input.readNBytes(56) token0825 = input.readNBytes(56)
input.skip(6) input.skip(6)
loginTime = input.readInt() loginTime = input.readInt()
......
...@@ -239,6 +239,7 @@ public class TEACryptor { ...@@ -239,6 +239,7 @@ public class TEACryptor {
} }
public byte[] encrypt(byte[] plaintext) { public byte[] encrypt(byte[] plaintext) {
System.out.println("TEA加密, 原文=" + UtilsKt.toUHexString(plaintext));
return encrypt(plaintext, 0, plaintext.length); return encrypt(plaintext, 0, plaintext.length);
} }
......
...@@ -3,6 +3,7 @@ package net.mamoe.mirai.util ...@@ -3,6 +3,7 @@ package net.mamoe.mirai.util
import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.Protocol
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.DataOutputStream import java.io.DataOutputStream
import java.lang.reflect.Field
import java.util.* import java.util.*
import java.util.zip.CRC32 import java.util.zip.CRC32
...@@ -28,33 +29,80 @@ object Utils { ...@@ -28,33 +29,80 @@ object Utils {
} }
} }
fun ByteArray.toHexString(): String = toHexString(" ")
fun ByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator) fun ByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
@ExperimentalUnsignedTypes
fun ByteArray.toUHexString(separator: String = " "): String = this.toUByteArray().toHexString(separator)
@ExperimentalUnsignedTypes
fun ByteArray.toUHexString(): String = this.toUByteArray().toHexString()
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun UByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator) fun UByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun Byte.toHexString(): String = this.toUByte().toString(16) fun UByteArray.toHexString(): String = toHexString(" ")
@ExperimentalUnsignedTypes
fun Byte.toHexString(): String = this.toUByte().toString(16)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this) fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this) fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
@ExperimentalUnsignedTypes//todo test that @ExperimentalUnsignedTypes
fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() } fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() }
@ExperimentalUnsignedTypes
fun String.hexToByte(): Byte = hexToBytes()[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()
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray(); open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray();
} }
fun lazyEncode(t: (ByteArrayDataOutputStream) -> Unit): ByteArray = ByteArrayDataOutputStream().let { t(it); return it.toByteArray() }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun getRandomKey(length: Int): ByteArray { fun getRandomKey(length: Int): ByteArray {
val bytes = LinkedList<Byte>(); val bytes = LinkedList<Byte>();
for (i in 0..length) bytes.add((Math.random() * 255).toByte()) repeat(length) { bytes.add((Math.random() * 255).toByte()) }
return bytes.toByteArray(); return bytes.toByteArray();
} }
fun getCrc32(key: ByteArray): Long = with(CRC32()) { update(key); return@with this.value }; fun getCrc32(key: ByteArray): Int = CRC32().let { it.update(key); it.value.toInt() }
\ No newline at end of file
/**
* 获取类的所有字段(类成员变量), 包括父类的和私有的. <br></br>
* 相当于将这个类和它所有父类的 [Class.getDeclaredFields] 都合并成一个 [List] <br></br>
* 不会排除重名的字段. <br></br>
*
* @param clazz class
*
* @return field list
*/
@Throws(SecurityException::class)
fun Any.getAllDeclaredFields(): List<Field> {
var clazz: Class<*> = this.javaClass;
val list = LinkedList<Field>()
loop@ do {
if (!clazz.name.contains("net.mamoe")) {
break@loop
}
list.addAll(clazz.declaredFields.filter { (it.name == "Companion" || it.name == "input").not() }.toList())
if (clazz.superclass == null) {
break
}
clazz = clazz.superclass
} while (clazz != Object::javaClass)
return list
}
/**
* @author NaturalHG
* This could be used to check packet encoding..
* but better to run under UNIX
*/
public class HaxComparator {
/**
* a string result
*/
private static String RED = "\033[31m";
private static String GREEN = "\033[33m";
public static String compare(String hax1s, String hax2s){
StringBuilder builder = new StringBuilder();
String[] hax1 = hax1s.trim().split(" ");
String[] hax2 = hax2s.trim().split(" ");
if(hax1.length == hax2.length){
builder.append(GREEN).append("长度一致:").append(hax1.length);
}else{
builder.append(RED).append("长度不一致").append(hax1.length).append("/").append(hax2.length);
}
StringBuilder hax1b = new StringBuilder();
StringBuilder hax2b = new StringBuilder();
int dif = 0;
for (int i=0;i<Math.max(hax1.length,hax2.length);++i){
String h1 = null;
String h2 = null;
boolean isDif = false;
if(hax1.length <= i){
h1 = RED + "__";
isDif = true;
}
if(hax2.length <= i){
h2 = RED + "__";
isDif = true;
}
if(h1 == null && h2 == null){
h1 = hax1[i];
h2 = hax2[i];
if(h1.equals(h2)){
h1 = GREEN + h1;
h2 = GREEN + h2;
}else{
h1 = RED + h1;
h2 = RED + h2;
isDif = true;
}
}else{
if(h1 == null){
h1 = RED + hax1[i];
}
if(h2 == null){
h2 = RED + hax2[i];
}
}
hax1b.append(h1).append(" ");
hax2b.append(h2).append(" ");
if(isDif){
++dif;
}
}
return (builder.append(" ").append(dif).append(" 个不同").append("\n").append(hax1b).append("\n").append(hax2b)).toString();
}
public static void main(String[] args){
System.out.println(HaxComparator.compare("00 01 09 00 70 00 01 23 7B FE 83 D1 37 64 46 84 9D E9 9C E7 BB 8E 44 00 38 9B A4 3B C2 BB 49 4C DA B0 A5 5C C8 27 29 74 EF CB 38 59 4E 03 C8 15 C6 F9 BF 3F 88 22 7E 22 5B 48 02 71 59 1A 2C C8 42 BA 81 76 66 0C 46 91 89 6C B2 17 BF 2A 00 F8 8B 00 20 7C 28 07 3D AA 24 EF B4 49 9D 85 7F 4C F5 41 56 F4 1F AD 53 81 9F C1 03 F3 03 65 DD 0C 04 CC 68 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6","AA CC AA DD EE GG HH"));
}
}
import kotlin.ranges.IntRange;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import net.mamoe.mirai.network.Protocol;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* This could be used to check packet encoding..
* but better to run under UNIX
*
* @author NaturalHG
*/
public class HexComparator {
/**
* a string result
*/
private static final String RED = "\033[31m";
private static final String GREEN = "\033[33m";
private static final String UNKNOWN = "\033[30m";
private static final String BLUE = "\033[34m";
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));
}};
private final List<Match> matches = new LinkedList<>();
private ConstMatcher(String hex) {
CONST_FIELDS.forEach(field -> {
for (IntRange match : match(hex, field)) {
matches.add(new Match(match, field.getName()));
}
});
}
private String getMatchedConstName(int hexNumber) {
for (Match match : this.matches) {
if (match.range.contains(hexNumber)) {
return match.constName;
}
}
return null;
}
private static List<IntRange> match(String hex, Field field) {
final String constValue;
try {
constValue = ((String) field.get(null)).trim();
if (constValue.length() / 3 <= 3) {//Minimum numbers of const hex bytes
return new LinkedList<>();
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassCastException ignored) {
return new LinkedList<>();
}
return new LinkedList<>() {{
int index = 0;
while ((index = hex.indexOf(constValue, index + 1)) != -1) {
add(new IntRange(index / 3, (index + constValue.length()) / 3));
}
}};
}
@ToString
@Getter
@AllArgsConstructor
private static class Match {
private IntRange range;
private String constName;
}
}
private static String compare(String hex1s, String hex2s) {
StringBuilder builder = new StringBuilder();
String[] hex1 = hex1s.trim().replace("\n", "").split(" ");
String[] hex2 = hex2s.trim().replace("\n", "").split(" ");
ConstMatcher constMatcher1 = new ConstMatcher(hex1s);
ConstMatcher constMatcher2 = new ConstMatcher(hex2s);
if (hex1.length == hex2.length) {
builder.append(GREEN).append("长度一致:").append(hex1.length);
} else {
builder.append(RED).append("长度不一致").append(hex1.length).append("/").append(hex2.length);
}
StringBuilder numberLine = new StringBuilder();
StringBuilder hex1b = new StringBuilder();
StringBuilder hex2b = new StringBuilder();
int dif = 0;
for (int i = 0; i < Math.max(hex1.length, hex2.length); ++i) {
String h1 = null;
String h2 = null;
boolean isDif = false;
if (hex1.length <= i) {
h1 = RED + "__";
isDif = true;
} else {
String matchedConstName = constMatcher1.getMatchedConstName(i);
if (matchedConstName != null) {
h1 = BLUE + hex1[i];
}
}
if (hex2.length <= i) {
h2 = RED + "__";
isDif = true;
} else {
String matchedConstName = constMatcher2.getMatchedConstName(i);
if (matchedConstName != null) {
h2 = BLUE + hex2[i];
}
}
if (h1 == null && h2 == null) {
h1 = hex1[i];
h2 = hex2[i];
if (h1.equals(h2)) {
h1 = GREEN + h1;
h2 = GREEN + h2;
} else {
h1 = RED + h1;
h2 = RED + h2;
isDif = true;
}
} else {
if (h1 == null) {
h1 = RED + hex1[i];
}
if (h2 == null) {
h2 = RED + hex2[i];
}
}
numberLine.append(UNKNOWN).append(getNumber(i)).append(" ");
hex1b.append(" ").append(h1).append(" ");
hex2b.append(" ").append(h2).append(" ");
if (isDif) {
++dif;
}
}
return (builder.append(" ").append(dif).append(" 个不同").append("\n")
.append(numberLine).append("\n")
.append(hex1b).append("\n")
.append(hex2b))
.toString();
}
private static String getNumber(int number) {
if (number < 10) {
return "00" + number;
}
if (number < 100) {
return "0" + number;
}
return String.valueOf(number);
}
public static void main(String[] args) {
System.out.println(HexComparator.compare(
//mirai
"01 12 00 38 D7 B4 57 68 68 BA 91 9D 2C 6F F0 B8 1A 77 4A DC 10 FE 74 E6 03 CE EA 90 5A 43 FD 19 21 94 EF 41 C3 2B 48 B7 91 70 DD AE 47 EA C7 EC 69 5A 6D 16 3B CA E8 DC 82 81 24 74 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 78 F4 FC F9 F2 B0 04 32 4A 01 F7 0B 23 7A 5E 30 E9 42 83 89 C4 D2 7A F7 7D 6E 71 FF FC 97 81 3A FC 11 75 3B D6 7C E8 C2 04 3E CD B1 34 57 C3 B4 AF 40 87 BD 06 18 7F 7B E8 8E F5 42 0F A8 A8 87 44 3A A5 51 69 61 F1 12 F4 94 DE BA 37 D9 50 5C 03 ED CB DE 6E 68 B4 DE 79 6E BF A9 07 D2 E5 56 7A AF 35 12 00 0C 4D 9D F4 E5 0C 36 9C 5C 5A CE F7 2D 95 28 82 8A FC E5 00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B 00 1A 00 40 56 5C 1A 38 F9 6A 88 F8 34 EF 68 FC 83 9D 61 9B 7A 07 F6 37 CD 1E C4 9A C9 B2 81 B3 F5 67 C4 74 63 23 30 64 E8 32 6F BD 35 14 0D 75 2D DF 0F 38 80 D3 3C 11 0D 1B 74 EF C8 6D 54 42 E7 DB 94 B9 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 01 10 00 3C 00 01 00 38 E0 65 0C 69 9A EE D9 90 CE 5D AF 23 6B 49 03 0D 98 47 25 3F B5 BD 88 BB 54 50 72 E0 37 8E 66 ED A6 37 18 77 71 5D 66 A6 A3 CD A5 BC 9B CD 87 42 DB 41 59 3E 54 A7 90 DC 03 12 00 05 01 00 00 00 01 05 08 00 05 10 00 00 00 00 03 13 00 19 01 01 02 00 10 04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA 00 00 00 00 01 02 00 62 00 01 04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48 00 38 E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3 00 14 32 8C B5 CB 10 2E 0A 31 F2 EB 6D FC 13 CB 14 83 31 CD 75 C6"
,
//e
"01 12 00 38 D5 CC FC 5E BF 39 4C 07 7F FF AE 3C C2 10 E0 0E 3D C1 7B 6C 1C 58 9C 97 AB DE DC 4C B7 8E AB DA 77 BE 5F AD 8D 3C EA 7D B8 3D 5E B3 5B 6B DD 32 E6 A5 0C 6F B7 93 E4 C3 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 64 5C 48 D5 BF 98 6A 81 8F B5 09 DA A5 83 0E 45 BB 99 9B 03 42 2A 87 95 48 88 52 0D 5F 0B C1 4D A7 5F BF 60 4F 3D A1 04 D3 B4 E4 D2 45 71 5C 74 95 80 86 45 E0 26 EA B2 B1 09 0B 56 22 68 7C 5D 8D 9E 69 E4 C5 4E 0C EA F5 6F 90 FF 4B 43 43 EB 4F 76 45 70 DA 12 C7 1E A5 14 B8 5B 78 79 75 5E 2C F3 5D 1A C4 39 D5 AE 1A 70 EC AF A1 F5 FF D6 D3 B9 C6 DA 71 7E 15 52 00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B 00 1A 00 40 9D AB 45 74 6A E5 3F E2 8E 81 16 6C BB FA 0D A1 37 28 2F B9 02 3D EB 07 C7 ED 95 99 F9 35 27 35 58 67 4A FA 6E E4 89 37 8A 00 3B 19 C5 15 7E F6 83 D5 CF 66 9C FD 10 9F 27 90 31 3B 2E 98 F9 4C 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 01 10 00 3C 00 01 00 38 3A 51 49 BC 3C 44 78 A1 A7 6D B7 98 03 05 9F 42 E1 15 E5 53 0C C1 03 82 5E AE AD FC 44 C6 E9 85 66 51 F2 E2 67 B4 60 DC 89 EC E4 56 13 52 E6 AA C4 5A D1 FA 3D E7 10 92 03 12 00 05 01 00 00 00 01 05 08 00 05 01 00 00 00 00 03 13 00 19 01 01 02 00 10 04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA 00 00 00 00 01 02 00 62 00 01 04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48 00 38 E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3 00 14 D5 4E 31 3E 5E B3 28 6C 94 FB 25 CA E8 C4 A4 28 09 02 B2 58"
));
System.out.println(HexComparator.compare(
//e
"90 5E 39 DF 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 7B 7B 7B 7B 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",
//mirai
"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"
));
}
}
...@@ -63,12 +63,6 @@ ...@@ -63,12 +63,6 @@
</build> </build>
<dependencies> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.intellij</groupId> <groupId>com.intellij</groupId>
...@@ -94,13 +88,6 @@ ...@@ -94,13 +88,6 @@
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna --> <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
...@@ -114,6 +101,13 @@ ...@@ -114,6 +101,13 @@
<version>2.8.5</version> <version>2.8.5</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.3.0-M2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
......
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