This commit is contained in:
Him188moe 2019-08-17 15:43:42 +08:00
parent 2ff1e9bf9e
commit 88d2fa0449
9 changed files with 223 additions and 201 deletions

View File

View File

@ -97,7 +97,7 @@ public class MiraiServer {
Robot robot = new Robot(1994701021L);
try {
robot.connect(Protocol.SERVER_IP.get(2), 8000);
robot.connect(Protocol.Companion.getSERVER_IP().get(2), 8000);
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);

View File

@ -1,20 +1,19 @@
package net.mamoe.mirai.network;
package net.mamoe.mirai.network
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.net.InetAddress
import java.util.*
import java.util.stream.Collectors
/**
* @author Him188moe @ Mirai Project
*/
public interface Protocol {
List<String> SERVER_IP = new ArrayList<>() {{
add("183.60.56.29");
interface Protocol {
companion object {
val SERVER_IP: ArrayList<String> = object : ArrayList<String>() {
init {
add("183.60.56.29")
List.of(
arrayOf(
"sz2.tencent.com",
"sz3.tencent.com",
"sz4.tencent.com",
@ -22,40 +21,42 @@ public interface Protocol {
"sz6.tencent.com",
"sz8.tencent.com",
"sz9.tencent.com"
).forEach(s -> {
try {
SERVER_IP.add(InetAddress.getByName(s).getHostAddress());
} catch (UnknownHostException ignored) {
}
});
}};
String head = "02";
String ver = "37 13 ";
String fixVer = "03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 ";
String tail = " 03";
String _fixVer = "02 00 00 00 01 01 01 00 00 68 20 ";
String _0825data0 = "00 18 00 16 00 01 ";
String _0825data2 = "00 00 04 53 00 00 00 01 00 00 15 85 ";
String _0825key = "A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D";
String redirectionKey = "A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B";
String publicKey = "02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3";
String shareKey = "1A E9 7F 7D C9 73 75 98 AC 02 E0 80 5F A9 C6 AF";
String _0836fix = "06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 ";
String _00BaKey = "C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94";
String _00BaFixKey = "69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A";
String encryptKey = "“BA 42 FF 01 CF B4 FF D2 12 F0 6E A7 1B 7C B3 08”";
static byte[] hexToBytes(String hex) {
var list = Arrays.stream(hex.split(" ")).map(String::trim).map(s -> Byte.valueOf(s, 16)).collect(Collectors.toList());
var buff = new byte[list.size()];
for (int i = 0; i < list.size(); i++) {
buff[i] = list.get(i);
}
return buff;
).forEach { this.add(InetAddress.getByName(it).hostAddress) }
}
}
const val head = "02"
const val ver = "37 13 "
const val fixVer = "03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 "
const val tail = " 03"
const val _fixVer = "02 00 00 00 01 01 01 00 00 68 20 "
const val _0825data0 = "00 18 00 16 00 01 "
const val _0825data2 = "00 00 04 53 00 00 00 01 00 00 15 85 "
const val _0825key = "A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D"
const val redirectionKey = "A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B"
const val publicKey = "02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3"
const val shareKey = "1A E9 7F 7D C9 73 75 98 AC 02 E0 80 5F A9 C6 AF"
const val _0836fix = "06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 "
const val _00BaKey = "C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94"
const val _00BaFixKey = "69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A"
const val encryptKey = "“BA 42 FF 01 CF B4 FF D2 12 F0 6E A7 1B 7C B3 08”"
fun hexToBytes(hex: String): ByteArray = Arrays
.stream(hex.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
.map { value -> value.trim { it <= ' ' } }
.map { s -> s.toInt(16).toByte() }
.collect(Collectors.toList()).toByteArray()
@ExperimentalUnsignedTypes
fun hexToUBytes(hex: String): UByteArray = Arrays
.stream(hex.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
.map { value -> value.trim { it <= ' ' } }
.map { s -> s.toInt(16).toByte() }
.collect(Collectors.toList()).toByteArray().toUByteArray()
}
}

View File

@ -1,28 +0,0 @@
package net.mamoe.mirai.network.packet.client;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.mamoe.mirai.network.Protocol;
import net.mamoe.mirai.network.packet.PacketId;
import net.mamoe.mirai.util.TEAEncryption;
import java.io.IOException;
/**
* @author Him188moe @ Mirai Project
*/
@EqualsAndHashCode(callSuper = true)
@Data
@PacketId(0x00_58)
public class ClientHeartbeatPacket extends ClientPacket {
public long qq;
public byte[] sessionKey;//登录后获得
@Override
public void encode() throws IOException {
this.writeRandom(2);
this.writeQQ(qq);
this.writeHex(Protocol.fixVer);
this.write(TEAEncryption.encrypt(new byte[]{0x00, 0x01, 0x00, 0x01}, sessionKey));
}
}

View File

@ -0,0 +1,23 @@
package net.mamoe.mirai.network.packet.client
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.util.TEAEncryption
import java.io.IOException
/**
* @author Him188moe @ Mirai Project
*/
@PacketId(value = 0x00_58)
class ClientHeartbeatPacket : ClientPacket() {
var qq: Long = 0
var sessionKey: ByteArray? = null//登录后获得
@Throws(IOException::class)
override fun encode() {
this.writeRandom(2)
this.writeQQ(qq)
this.writeHex(Protocol.fixVer)
this.write(TEAEncryption.encrypt(byteArrayOf(0x00, 0x01, 0x00, 0x01), sessionKey))
}
}

View File

@ -1,58 +0,0 @@
package net.mamoe.mirai.network.packet.client;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.mamoe.mirai.network.Protocol;
import net.mamoe.mirai.network.packet.PacketId;
import net.mamoe.mirai.util.TEAEncryption;
import net.mamoe.mirai.util.Utils;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Him188moe @ Mirai Project
*/
@EqualsAndHashCode(callSuper = true)
@Data
@PacketId(0x08_25_31_01)
public class ClientLoginPacket extends ClientPacket {
public long qq;
@Override
public void encode() throws IOException {
this.writeQQ(qq);
this.writeHex(Protocol.fixVer);
this.writeHex(Protocol._0825key);
//TEA 加密
this.write(TEAEncryption.encrypt(new ClientPacket() {
@Override
public void encode() throws IOException {
this.writeHex(Protocol._0825data0);
this.writeHex(Protocol._0825data2);
this.writeQQ(qq);
this.writeHex("00 00 00 00 03 09 00 08 00 01");
//this.writeIp(Protocol.SERVER_IP.get(2));
this.writeIp("123456789");
this.writeHex("00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19");
this.writeHex(Protocol.publicKey);
}
}.encodeToByteArray(), Protocol.hexToBytes(Protocol._0825key)));
}
public static void main(String[] args) throws IOException {
try {
var pk = new ClientLoginPacket();
pk.qq = 1994701021;
pk.encode();
pk.writeHex(Protocol.tail);
System.out.println("pk.toByteArray() = " + Arrays.toString(pk.toByteArray()));
System.out.println(Utils.INSTANCE.toHexString(pk.toByteArray()));
} catch (Throwable e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,55 @@
package net.mamoe.mirai.network.packet.client
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.util.ByteArrayDataOutputStream
import net.mamoe.mirai.util.TEAEncryption
import net.mamoe.mirai.util.toHexString
import java.io.IOException
/**
* @author Him188moe @ Mirai Project
*/
@PacketId(0x08_25_31_01)
class ClientLoginPacket : ClientPacket() {
var qq: Long = 0
@Throws(IOException::class)
override fun encode() {
this.writeQQ(qq)
this.writeHex(Protocol.fixVer)
this.writeHex(Protocol._0825key)
//TEA 加密
this.write(TEAEncryption.encrypt(object : ByteArrayDataOutputStream() {
@Throws(IOException::class)
override fun toByteArray(): ByteArray {
this.writeHex(Protocol._0825data0)
this.writeHex(Protocol._0825data2)
this.writeQQ(qq)
this.writeHex("00 00 00 00 03 09 00 08 00 01")
//this.writeIp(Protocol.SERVER_IP.get(2));
this.writeIp("123456789")
this.writeHex("00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19")
this.writeHex(Protocol.publicKey)
return super.toByteArray()
}
}.toByteArray(), Protocol.hexToBytes(Protocol._0825key)))
}
}
@ExperimentalUnsignedTypes
fun main() {
val pk = ClientLoginPacket()
pk.qq = 1994701021
pk.encode()
pk.writeHex(Protocol.tail)
println("pk.toByteArray() = " + pk.toUByteArray().contentToString())
println(pk.toUByteArray().toHexString(" "))
}
//mirai: 02 37 13 08 25 31 01 00 00 00 00 76 E4 B8 DD 03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D 94 06 D9 3B 40 B5 E2 39 58 F5 E1 71 46 63 FF 6C CE 1E F1 BF CB F5 04 67 96 81 01 7C EF 47 10 15 45 8A 59 F7 B4 39 48 A3 E1 9C 74 3C DC 8E 7E 2F CF B6 C1 0C 2C C6 D6 7F DC 98 12 9C 88 35 29 33 C6 98 A9 81 C7 7B 2D 76 00 67 A1 DD 82 1E 12 04 DF DF 48 18 E0 C3 C8 54 B5 C2 16 A8 C4 CD BD 7D FD 5E 2A A9 74 68 82 44 F7 0D 7D 0E 6C 4F C8 05 03
//epl : 02 37 13 08 25 31 02 B8 DD 03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B D9 9E E9 58 5A E5 46 0D 40 D0 A5 A2 DF 48 8D 23 FB 25 C1 1A 4B D1 27 BA AB B2 69 AB DE 91 C0 63 65 2B 3A 0F 06 0C 3F EC 5C 48 A7 AE 25 06 3F 3C 7A A2 46 91 22 8E B2 A0 41 3F 5D C8 A5 C6 64 64 62 11 A1 9E 14 51 28 39 41 01 07 B5 8B 98 33 AB 50 AD 2F 05 8E F1 17 D7 1D 67 61 1B CD E9 B8 C6 A5 A7 F9 48 F7 BE 05 BC 03

View File

@ -1,81 +1,83 @@
package net.mamoe.mirai.network.packet.client;
package net.mamoe.mirai.network.packet.client
import lombok.Getter;
import net.mamoe.mirai.network.Protocol;
import net.mamoe.mirai.network.packet.Packet;
import net.mamoe.mirai.network.packet.PacketId;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import lombok.Getter
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.Packet
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.util.ByteArrayDataOutputStream
import java.io.DataOutputStream
import java.io.IOException
/**
* @author Him188moe @ Mirai Project
*/
public abstract class ClientPacket extends DataOutputStream implements Packet {
abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
@Getter
private final int packageId;
val packageId: Int
public ClientPacket() {
super(new ByteArrayOutputStream());
var annotation = this.getClass().getAnnotation(PacketId.class);
packageId = annotation.value();
init {
val annotation = this.javaClass.getAnnotation(PacketId::class.java)
packageId = annotation.value
try {
this.writeHex(Protocol.head);
this.writeHex(Protocol.ver);
writePacketId();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.writeHex(Protocol.head)
this.writeHex(Protocol.ver)
writePacketId()
} catch (e: IOException) {
throw RuntimeException(e)
}
protected void writeIp(String ip) throws IOException {
for (String s : ip.split("\\.")) {
this.writeInt(Integer.parseInt(s));
}
}
protected void writePacketId() throws IOException {
this.writeInt(this.packageId);
@Throws(IOException::class)
fun writePacketId() {
this.writeInt(this@ClientPacket.packageId)
}
protected void writeHex(String hex) throws IOException {
for (String s : hex.split(" ")) {
s = s.trim();
if (s.isEmpty()) {
continue;
}
this.writeByte(Byte.valueOf(s, 16));
}
}
protected void writeRandom(int length) throws IOException {
for (int i = 0; i < length; i++) {
this.writeByte((byte) (int) (Math.random() * 255));
}
}
protected void writeQQ(long qq) throws IOException {
this.writeLong(qq);
}
/**
* Encode this packet.
* <p>
* Before sending the packet, an {@linkplain Protocol#tail tail} will be added.
*
*
* Before sending the packet, an [tail][Protocol.tail] will be added.
*/// TODO: 2019/8/9 添加 tail
public abstract void encode() throws IOException;
@Throws(IOException::class)
abstract fun encode()
public byte[] toByteArray() {
return ((ByteArrayOutputStream) this.out).toByteArray();
}
public final byte[] encodeToByteArray() throws IOException {
encode();
return toByteArray();
@Throws(IOException::class)
fun encodeToByteArray(): ByteArray {
encode()
return toByteArray()
}
}
@Throws(IOException::class)
fun DataOutputStream.writeIp(ip: String) {
for (s in ip.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
this.writeInt(Integer.parseInt(s))
}
}
@Throws(IOException::class)
fun DataOutputStream.writeHex(hex: String) {
for (s in hex.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
if (s.isEmpty()) {
continue
}
this.writeByte(Integer.parseInt(s, 16))
}
}
@Throws(IOException::class)
fun DataOutputStream.writeRandom(length: Int) {
for (i in 0 until length) {
this.writeByte((Math.random() * 255).toInt().toByte().toInt())
}
}
@Throws(IOException::class)
fun DataOutputStream.writeQQ(qq: Long) {
this.writeLong(qq)
}

View File

@ -1,16 +1,43 @@
package net.mamoe.mirai.util
import net.mamoe.mirai.network.Protocol
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
/**
* @author Him188moe @ Mirai Project
*/
object Utils {
fun toHexString(byteArray: ByteArray): String = byteArray.joinToString(" ") { it.toString(16) }
fun toHexString(byteArray: ByteArray, separator: String = ","): String = byteArray.joinToString(separator) {
var ret = it.toString(16).toUpperCase();
if (ret.length == 1) {
ret = "0$ret";
}
return@joinToString ret;
}
fun ByteArray.toHexString(): String = Utils.toHexString(this)
@ExperimentalUnsignedTypes
fun toHexString(byteArray: UByteArray, separator: String = ","): String = byteArray.joinToString(separator) {
var ret = it.toString(16).toUpperCase();
if (ret.length == 1) {
ret = "0$ret";
}
return@joinToString ret;
}
}
fun ByteArray.toHexString(separator: String = ", "): String = Utils.toHexString(this, separator)
@ExperimentalUnsignedTypes
fun UByteArray.toHexString(separator: String = ", "): String = Utils.toHexString(this, separator)
fun Byte.toHexString(): String = this.toString(16)
fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
@ExperimentalUnsignedTypes
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
@ExperimentalUnsignedTypes
open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray();
}