修复协议版本754后的Forge伪造支持

This commit is contained in:
SerendipityR 2022-08-24 01:38:05 +08:00 committed by GitHub
parent 992a9b7d75
commit 9049294010
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 248 additions and 30 deletions

View File

@ -8,7 +8,7 @@ import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.ProtocolLibs;
public class EndMinecraftPlusV2 {
public static String ver = "1.2.6";
public static String ver = "1.2.7";
public static Integer CfgVer = 2;
public static void main(String[] args) {

View File

@ -1,15 +1,16 @@
package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol;
import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.ProtocolLibs;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.*;
import com.github.steveice10.packetlib.packet.Packet;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Scanner;
public class MCForge {
private final MCForgeHandShake handshake;
@ -24,44 +25,93 @@ public class MCForge {
}
public void init() {
this.session.addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {
if (e.getPacket() instanceof ServerPluginMessagePacket) {
handle(e.getPacket());
} else if (e.getPacket().getClass().getSimpleName().equals("LoginPluginRequestPacket")) {
handshake.handle(e.getPacket());
if (ProtocolLibs.adaptAfter754) {
this.session.addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {
if (e.getPacket() instanceof ClientboundCustomPayloadPacket) {
handle(e.getPacket());
} else if (e.getPacket().getClass().getSimpleName().equals("ClientboundCustomQueryPacket")) {
handshake.newHandle(e.getPacket());
}
}
}
public void packetReceived(Session session, Packet packet) {
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ClientboundCustomPayloadPacket) {
newHandle((ClientboundCustomPayloadPacket) packet);
} else if (packet.getClass().getSimpleName().equals("ClientboundCustomQueryPacket")) {
handshake.newHandle(packet);
}
}
}
public void packetSending(PacketSendingEvent packetSendingEvent) {
public void packetSending(PacketSendingEvent packetSendingEvent) {
}
}
public void packetSent(Session session, Packet packet) {
public void packetSent(Session session, Packet packet) {
}
}
public void packetError(PacketErrorEvent packetErrorEvent) {
public void packetError(PacketErrorEvent packetErrorEvent) {
}
}
public void packetSent(PacketSentEvent e) {
}
public void packetSent(PacketSentEvent e) {
}
public void connected(ConnectedEvent e) {
modifyHost();
}
public void connected(ConnectedEvent e) {
modifyHost();
}
public void disconnecting(DisconnectingEvent e) {
}
public void disconnecting(DisconnectingEvent e) {
}
public void disconnected(DisconnectedEvent e) {
}
});
} else {
this.session.addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {
if (e.getPacket() instanceof ServerPluginMessagePacket) {
handle(e.getPacket());
} else if (e.getPacket().getClass().getSimpleName().equals("LoginPluginRequestPacket")) {
handshake.handle(e.getPacket());
}
}
public void disconnected(DisconnectedEvent e) {
}
});
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ServerPluginMessagePacket) {
handle((ServerPluginMessagePacket) packet);
} else if (packet.getClass().getSimpleName().equals("LoginPluginRequestPacket")) {
handshake.handle(packet);
}
}
public void packetSending(PacketSendingEvent packetSendingEvent) {
}
public void packetSent(Session session, Packet packet) {
}
public void packetError(PacketErrorEvent packetErrorEvent) {
}
public void packetSent(PacketSentEvent e) {
}
public void connected(ConnectedEvent e) {
modifyHost();
}
public void disconnecting(DisconnectingEvent e) {
}
public void disconnected(DisconnectedEvent e) {
}
});
}
}
public void handle(ServerPluginMessagePacket packet) {
@ -70,16 +120,32 @@ public class MCForge {
this.handshake.handle(packet);
break;
case "REGISTER":
case "minecraft:register": // 1.13
case "minecraft:register":
this.session.send(new ClientPluginMessagePacket(packet.getChannel(), packet.getData()));
break;
case "MC|Brand":
case "minecraft:brand": // 1.13
case "minecraft:brand":
this.session.send(new ClientPluginMessagePacket(packet.getChannel(), "fml,forge".getBytes()));
break;
}
}
public void newHandle(ClientboundCustomPayloadPacket packet) {
switch (packet.getChannel()) {
case "FML|HS":
this.handshake.handle(packet);
break;
case "REGISTER":
case "minecraft:register":
this.session.send(new ServerboundCustomPayloadPacket(packet.getChannel(), packet.getData()));
break;
case "MC|Brand":
case "minecraft:brand":
this.session.send(new ServerboundCustomPayloadPacket(packet.getChannel(), "fml,forge".getBytes()));
break;
}
}
public void modifyHost() {
try {
Class<?> cls = this.session.getClass().getSuperclass();

View File

@ -10,5 +10,6 @@ public abstract class MCForgeHandShake {
}
public abstract void handle(Packet recvPacket);
public abstract void newHandle(Packet recvPacket);
public abstract String getFMLVersion();
}

View File

@ -1,7 +1,9 @@
package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.io.stream.StreamNetOutput;
import com.github.steveice10.packetlib.packet.Packet;
@ -65,6 +67,57 @@ public class MCForgeHandShakeV1 extends MCForgeHandShake {
}
}
public void newHandle(Packet recvPacket) {
ClientboundCustomPayloadPacket packet = (ClientboundCustomPayloadPacket) recvPacket;
Session session = forge.session;
byte[] data = packet.getData();
int packetID = data[0];
switch (packetID) {
case 0: // Hello
newSendPluginMessage(session, packet.getChannel(), new byte[] { 0x01, 0x02 });
// ModList
ByteArrayOutputStream buf = new ByteArrayOutputStream();
StreamNetOutput out = new StreamNetOutput(buf);
try {
out.writeVarInt(2);
out.writeByte(forge.modList.size());
forge.modList.forEach((k, v) -> {
try {
out.writeString(k);
out.writeString(v);
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
newSendPluginMessage(session, packet.getChannel(), buf.toByteArray());
break;
case 2: // ModList
newSendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x02 }); // ACK(WAITING SERVER DATA)
break;
case 3: // RegistryData
newSendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x03 }); // ACK(WAITING SERVER COMPLETE)
break;
case -1: // HandshakeAck
int ackID = data[1];
switch (ackID) {
case 2: // WAITING CACK
newSendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x04 }); // PENDING COMPLETE
break;
case 3: // COMPLETE
newSendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x05 }); // COMPLETE
break;
default:
}
default:
}
}
public String getFMLVersion() {
return "FML";
}
@ -72,4 +125,8 @@ public class MCForgeHandShakeV1 extends MCForgeHandShake {
private void sendPluginMessage(Session session, String channel, byte[] data) {
session.send(new ClientPluginMessagePacket(channel, data));
}
private void newSendPluginMessage(Session session, String channel, byte[] data) {
session.send(new ServerboundCustomPayloadPacket(channel, data));
}
}

View File

@ -1,7 +1,9 @@
package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol;
import com.github.steveice10.mc.protocol.packet.login.client.LoginPluginResponsePacket;
import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundCustomQueryPacket;
import com.github.steveice10.mc.protocol.packet.login.server.LoginPluginRequestPacket;
import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket;
import com.github.steveice10.packetlib.io.buffer.ByteBufferNetInput;
import com.github.steveice10.packetlib.io.stream.StreamNetOutput;
import com.github.steveice10.packetlib.packet.Packet;
@ -112,6 +114,93 @@ public class MCForgeHandShakeV2 extends MCForgeHandShake {
}
}
public void newHandle(Packet recvPacket) {
ClientboundCustomQueryPacket packet = (ClientboundCustomQueryPacket) recvPacket;
if (!packet.getChannel().equals("fml:loginwrapper")) return;
try {
LoginWrapper loginWrapper = new LoginWrapper().fromBytes(packet.getData());
String targetNetworkReceiver = loginWrapper.getTargetNetworkReceiver();
ByteBufferNetInput in = new ByteBufferNetInput(ByteBuffer.wrap(loginWrapper.getPayload()));
int packetID = in.readByte();
switch (packetID) {
case Packet_S2CModList: {
// recv: S2CModList
final List<String> mods = new ArrayList<>();
int len = in.readVarInt();
for (int x = 0; x < len; x++)
mods.add(in.readString());
final Map<String, String> channels = new HashMap<>();
len = in.readVarInt();
for (int x = 0; x < len; x++)
channels.put(in.readString(), in.readString());
final List<String> registries = new ArrayList<>();
len = in.readVarInt();
for (int x = 0; x < len; x++)
registries.add(in.readString());
// send: C2SModListReply
ByteArrayOutputStream buf = new ByteArrayOutputStream();
StreamNetOutput out = new StreamNetOutput(buf);
out.writeByte(Packet_C2SModListReply);
out.writeVarInt(mods.size());
mods.forEach(m -> {
try {
out.writeString(m);
} catch (IOException e) {
e.printStackTrace();
}
});
out.writeVarInt(channels.size());
channels.forEach((k, v) -> {
try {
out.writeString(k);
out.writeString(v);
} catch (IOException e) {
e.printStackTrace();
}
});
// TODO: Fill with known hashes, which requires keeping a file cache (FMLHandshakeMessages.java)
out.writeVarInt(0); // empty map
/*
out.writeVarInt(registries.size());
registries.forEach(r -> {
try {
out.writeString(r);
out.writeString("");
} catch (IOException e) {
e.printStackTrace();
}
});
*/
newReply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray());
break;
}
case Packet_S2CRegistry:
case Packet_S2CConfigData: {
// recv: S2CRegistry
// send: C2SAcknowledge
ByteArrayOutputStream buf = new ByteArrayOutputStream();
StreamNetOutput out = new StreamNetOutput(buf);
out.writeByte(Packet_C2SAcknowledge);
newReply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray());
break;
}// recv: S2CConfigData
}
} catch (Exception ex) {
forge.session.disconnect("Failure to handshake", ex);
}
}
public String getFMLVersion() {
return "FML2";
}
@ -120,6 +209,10 @@ public class MCForgeHandShakeV2 extends MCForgeHandShake {
forge.session.send(new LoginPluginResponsePacket(id, new LoginWrapper(targetNetworkReceiver, payload).toBytes()));
}
private void newReply(int id, String targetNetworkReceiver, byte[] payload) throws IOException {
forge.session.send(new ServerboundCustomQueryPacket(id, new LoginWrapper(targetNetworkReceiver, payload).toBytes()));
}
static class LoginWrapper {
private String targetNetworkReceiver;
private byte[] payload;

View File

@ -51,6 +51,7 @@ public class MCForgeMOTD {
if (response.modinfo != null) {
for (Response.ModInfo.ModID modid : response.modinfo.modList) {
modList.put(modid.modid, modid.version);
LogUtil.doLog(0, modid.modid + " | " + modid.version, "[Debug]");
}
}
}