From d6bebef07cfce2e5c46379242eef7b6955c6f790 Mon Sep 17 00:00:00 2001 From: obvWolf Date: Thu, 1 Feb 2024 07:20:48 -0600 Subject: [PATCH] New ServerID system finished, filteraction has a string formatting bug. --- build.gradle | 5 +- .../github/thetrouper/sentinel/Sentinel.java | 35 ++- .../github/thetrouper/sentinel/auth/Auth.java | 2 +- .../sentinel/cmds/SentinelCommand.java | 20 ++ .../sentinel/server/FilterAction.java | 6 +- .../server/functions/Authenticator.java | 4 +- .../sentinel/server/functions/Telemetry.java | 232 +++++++++--------- .../sentinel/server/util/CipherUtils.java | 35 +++ 8 files changed, 191 insertions(+), 148 deletions(-) create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java diff --git a/build.gradle b/build.gradle index 157185f..f966719 100644 --- a/build.gradle +++ b/build.gradle @@ -29,9 +29,8 @@ repositories { dependencies { compileOnly 'org.spigotmc:spigot-api:1.20.4-R0.1-SNAPSHOT' implementation 'com.google.code.gson:gson:2.10.1' - implementation("club.minnced:discord-webhooks:0.8.4") + implementation 'club.minnced:discord-webhooks:0.8.4' implementation files("libs/PDK-1.3.3.jar") - } def targetJavaVersion = 16 @@ -63,4 +62,4 @@ compileJava.options.encoding("UTF-8") tasks.withType(JavaCompile) { options.encoding = "UTF-8" -} +} \ No newline at end of file diff --git a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java index dab7e55..6bd5420 100644 --- a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java +++ b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java @@ -2,9 +2,6 @@ package io.github.thetrouper.sentinel; import club.minnced.discord.webhook.WebhookClient; import club.minnced.discord.webhook.WebhookClientBuilder; -import club.minnced.discord.webhook.send.WebhookEmbed; -import club.minnced.discord.webhook.send.WebhookEmbedBuilder; -import club.minnced.discord.webhook.send.WebhookMessageBuilder; import io.github.itzispyder.pdk.PDK; import io.github.itzispyder.pdk.utils.misc.JsonSerializable; import io.github.thetrouper.sentinel.auth.Auth; @@ -21,7 +18,6 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; -import java.time.temporal.TemporalAccessor; import java.util.logging.Logger; public final class Sentinel extends JavaPlugin { @@ -46,6 +42,9 @@ public final class Sentinel extends JavaPlugin { public static final Logger log = Bukkit.getLogger(); public static boolean usesDynamicIP; + public static String serverID; + public static String license; + public static String IP; public static WebhookClient webclient; /** @@ -65,9 +64,9 @@ public final class Sentinel extends JavaPlugin { log.info("Language Status: (" + language.get("if-you-see-this-lang-is-broken") + ")"); log.info("Initializing Server ID..."); - String serverID = Authenticator.getServerID(); + serverID = Authenticator.getServerID(); - String license = mainConfig.plugin.license; + license = mainConfig.plugin.license; log.info("Pre-load finished!\n]====---- Requesting Authentication ----====[ \n- License Key: " + license + " \n- Server ID: " + serverID); log.info("Auth Requested..."); @@ -76,7 +75,7 @@ public final class Sentinel extends JavaPlugin { try { authStatus = Authenticator.authorize(license, serverID); authstatus = Auth.authorize(license, serverID); - + IP = Authenticator.getPublicIPAddress(); } catch (Exception e) { e.printStackTrace(); log.info("WTFFFF ARE YOU DOING MAN??????"); @@ -89,17 +88,15 @@ public final class Sentinel extends JavaPlugin { } case "MINEHUT" -> { usesDynamicIP = true; - String minehutStatus = Telemetry.loadTelemetryHook(serverID, license); - switch (minehutStatus) { - case "SUCCESS" -> { - authstatus = authstatus.replaceAll("ur a skid lmao","get out of here kiddo"); - log.info("Dynamic IP auth Success! " + authstatus); - startup(); - } - case "FAILURE" -> { - log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this."); - manager.disablePlugin(this); - } + Telemetry.initTelemetryHook(); + boolean minehutStatus = Telemetry.sendStartupLog(); + if (minehutStatus) { + authstatus = authstatus.replaceAll("ur a skid lmao", "get out of here kiddo"); + log.info("Dynamic IP auth Success! " + authstatus); + startup(); + } else { + log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this."); + manager.disablePlugin(this); } } case "INVALID-ID" -> { @@ -214,7 +211,7 @@ public final class Sentinel extends JavaPlugin { // Plugin shutdown logic log.info("Sentinel has disabled! (" + getDescription().getVersion() + ") Your server is now no longer protected!"); if (usesDynamicIP) { - Telemetry.sendShutdownLog(Authenticator.getServerID(), mainConfig.plugin.license); + Telemetry.sendShutdownLog(); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java b/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java index 8c5bcb7..083fcd9 100644 --- a/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java +++ b/src/main/java/io/github/thetrouper/sentinel/auth/Auth.java @@ -20,7 +20,7 @@ final String ENCRYPTION_KEY = -"If I am reading this and I am not a verified developer for Sentinel AntiNuke, I solely swear that my attempts to de-obfuscate this plugin are purely for virus investigation, and have malicious intentions such as cracking, leaking, or ratting this plugin."; +"If I am reading this and I am not a verified developer for Sentinel AntiNuke, I solely swear that my attempts to de-obfuscate this plugin are purely for rat checking, and have malicious intentions such as cracking, leaking, or ratting this plugin."; private static final diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java index 2503f78..79f94cd 100644 --- a/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java @@ -7,12 +7,18 @@ import io.github.itzispyder.pdk.commands.Permission; import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; +import io.github.thetrouper.sentinel.server.functions.Telemetry; +import io.github.thetrouper.sentinel.server.util.CipherUtils; import io.github.thetrouper.sentinel.server.util.Text; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; +import java.awt.*; import java.util.HashSet; @CommandRegistry(value = "sentinel",permission = @Permission("sentinel.debug")) public class SentinelCommand implements CustomCommand { @@ -51,6 +57,20 @@ public class SentinelCommand implements CustomCommand { debugMode = !debugMode; p.sendMessage(Text.prefix((debugMode ? "Enabled" : "Disabled") + " debug mode.")); } + case "encrypt" -> { + final String enc = CipherUtils.encrypt(args.getAll(2).toString()); + final String check = CipherUtils.decrypt(enc); + final String main = Text.prefix("Successfully encrypted \"&e" + check + "&7\" using AES.\n &7> &b" + enc); + Sentinel.log.info(args.getAll(2).toString() + "\n" + enc + "\n" + check); + TextComponent message = new TextComponent(); + message.setText(main); + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new net.md_5.bungee.api.chat.hover.content.Text("&bClick to copy!"))); + message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, enc)); + p.spigot().sendMessage(message); + } + case "tele" -> { + p.sendMessage(Telemetry.fetchTelemetryHook()); + } } } case "getHeat" -> { diff --git a/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java index 2fead64..3cdddca 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java @@ -122,7 +122,7 @@ public class FilterAction { description.append("%1$sPlayer: `%2$s` %3$s".formatted(Emojis.rightSort,offender.getName(),Emojis.target)); switch (type) { case SPAM_PUNISH -> { - description.append("%1$s%2$sHeat: `%3$s/%4$s`".formatted( + description.append("\n%1$s%2$sHeat: `%3$s/%4$s`".formatted( Emojis.space, Emojis.arrowRight, heatMap.get(offender), @@ -135,7 +135,7 @@ public class FilterAction { currentValue = e.getMessage(); } case SWEAR_PUNISH -> { - description.append("%1$s%2$sScore: `%3$s/%4$s`".formatted( + description.append("\n%1$s%2$sScore: `%3$s/%4$s`".formatted( Emojis.space, Emojis.arrowRight, scoreMap.get(offender), @@ -158,7 +158,7 @@ public class FilterAction { .setDescription(String.valueOf(description)) .addField(new WebhookEmbed.EmbedField(true,historyTitle,historyValue)) .addField(new WebhookEmbed.EmbedField(true,currentTitle,currentValue)) - .addField(new WebhookEmbed.EmbedField(false,"Executed: ", executed)) + .addField(new WebhookEmbed.EmbedField(false,"Executed: ", executed.replaceAll("%player%",offender.getName()))) .setThumbnailUrl("https://crafatar.com/avatars/" + offender.getUniqueId() + "?size=64&&overlay") .setColor(type.getColor().getRGB()) .build()) diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java index c3188de..d5860ee 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Authenticator.java @@ -23,8 +23,8 @@ public class Authenticator { public static String getServerID() { try { return MathUtils.SHA512(getPublicIPAddress()); - } catch (IOException e) { - return e.getMessage(); + } catch (Exception e) { + return "NULL"; } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java index 9cb5ee2..175b108 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Telemetry.java @@ -1,145 +1,137 @@ package io.github.thetrouper.sentinel.server.functions; +import club.minnced.discord.webhook.WebhookClient; +import club.minnced.discord.webhook.WebhookClientBuilder; +import club.minnced.discord.webhook.send.WebhookEmbed; +import club.minnced.discord.webhook.send.WebhookEmbedBuilder; +import club.minnced.discord.webhook.send.WebhookMessage; +import club.minnced.discord.webhook.send.WebhookMessageBuilder; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.discord.DiscordWebhook; +import io.github.thetrouper.sentinel.data.Emojis; +import io.github.thetrouper.sentinel.server.util.CipherUtils; +import io.github.thetrouper.sentinel.server.util.ServerUtils; import java.awt.*; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; -import java.net.InetAddress; +import java.net.HttpURLConnection; import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Telemetry { - - public Telemetry() throws UnknownHostException { - } - static InetAddress IP; - - static { - try { - IP = InetAddress.getLocalHost(); - } catch (UnknownHostException e) { - throw new RuntimeException(e); - } + public static WebhookClient telemetryHook; + public static void initTelemetryHook() { + WebhookClientBuilder builder = new WebhookClientBuilder(fetchTelemetryHook()); + builder.setThreadFactory((job) -> { + Thread thread = new Thread(job); + thread.setName("WebhookThread"); + thread.setDaemon(true); + return thread; + }); + builder.setWait(true); + telemetryHook = builder.build(); } - public static String telemetryHook; - - public static String loadTelemetryHook(String serverID, String licenseKey) { - String hook = ""; + public static boolean sendStartupLog() { + WebhookMessage embed = new WebhookMessageBuilder() + .setUsername("Sentinel Anti-Nuke | Telemetry") + .setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"). + addEmbeds(new WebhookEmbedBuilder() + .setAuthor(new WebhookEmbed.EmbedAuthor("Server Startup Log",null,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/")) + .setTitle(new WebhookEmbed.EmbedTitle("A server has started up successfully",null)) + .setDescription("Server " + Sentinel.serverID + "\n" + + Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" + + Emojis.rightSort + " IP: ||" + Sentinel.IP + "||") + .setColor(Color.GREEN.getRGB()) + .build()) + .build(); try { - URL url = new URL("https://sentinelauth.000webhostapp.com/telemetrykey.html"); - BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); - List lines = readLines(reader); - - for (String line : lines) { - if (line.contains("data-id")) { - hook = extractValue(line, "data-hook"); - telemetryHook = hook; - Map response = sendStartupLog(serverID,licenseKey); - - if (response.containsKey("SUCCESS")) { - Sentinel.log.info("Successfully grabbed telemetry hook"); - return "SUCCESS"; - } else { - Sentinel.log.info("An Error occurred while attempting to connect to the telemetry hook: " + response.get("ERROR")); - return "FAIL"; - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return "ERROR"; - } - - public static Map testWebhook(String hook) { - Map response = new HashMap<>(); - response.put("SUCCESS", "NULL"); - DiscordWebhook webhook = new DiscordWebhook(hook); - DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject() - .setAuthor("Test Success!", "", "") - .setDescription("Connected to webhook") - .setColor(Color.GREEN); - webhook.addEmbed(embed); - try { - webhook.execute(); - } catch (IOException e) { - response.clear(); - response.put("ERROR", e.toString()); - return response; - } - return response; - } - - public static List readLines(BufferedReader reader) { - try { - List lines = new ArrayList<>(); - String line = reader.readLine(); - while (line != null) { - lines.add(line); - line = reader.readLine(); - } - reader.close(); - return lines; + telemetryHook.send(embed); + return true; } catch (Exception ex) { + Sentinel.log.info("Failed to initialize dynamic auth!"); + return false; + } + } + + public static boolean sendShutdownLog() { + WebhookMessage embed = new WebhookMessageBuilder() + .setUsername("Sentinel Anti-Nuke | Telemetry") + .setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png"). + addEmbeds(new WebhookEmbedBuilder() + .setAuthor(new WebhookEmbed.EmbedAuthor("Server Shutdown Log",null,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/")) + .setTitle(new WebhookEmbed.EmbedTitle("A server has shut down successfully",null)) + .setDescription("Server " + Sentinel.serverID + "\n" + + Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" + + Emojis.rightSort + " IP: ||" + Sentinel.IP + "||") + .setColor(Color.RED.getRGB()) + .build()) + .build(); + try { + telemetryHook.send(embed); + return true; + } catch (Exception ex) { + Sentinel.log.info("Failed to send dynamic shutdown!"); + return false; + } + } + + public static String fetchTelemetryHook() { + try { + final String webhook = extractWebhook(fetchHtmlContent("https://trouper.me/auth/telemetry")); + ServerUtils.sendDebugMessage("Original Webhook: " + webhook); + + String webhookIdPart = webhook.replaceAll(".*/(\\d+)/([^/]+.*)$", "/$1/"); + ServerUtils.sendDebugMessage("Webhook ID Part: " + webhookIdPart); + + String encrypted = webhook.replaceAll(".*/\\d+/([^/]+.*)$", "$1"); + ServerUtils.sendDebugMessage("Encrypted Part: " + encrypted); + + String isolated = webhook.replaceAll("/\\d+/([^/]+.*)$", ""); + ServerUtils.sendDebugMessage("Isolated Part: " + isolated); + + String decrypted = isolated + webhookIdPart + CipherUtils.decrypt(encrypted); + ServerUtils.sendDebugMessage("Decrypted Result: " + decrypted); + + return decrypted; + } catch (Exception ex) { + Sentinel.log.warning("FAILED TO LOAD TELEMETRY (Are the servers up?)"); ex.printStackTrace(); + return "NULL"; } - return new ArrayList<>(); } - public static String extractValue(String line, String attribute) { - int start = line.indexOf(attribute + "=\"") + attribute.length() + 2; - int end = line.indexOf("\"", start); - return line.substring(start, end); - } + private static String fetchHtmlContent(String urlString) throws Exception { + URL url = new URL(urlString); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); - public static Map sendStartupLog(String serverID, String licenseKey) { - Map response = new HashMap<>(); - response.put("SUCCESS", "NULL"); - DiscordWebhook webhook = new DiscordWebhook(telemetryHook); - DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject() - .setAuthor("Server Startup Log", "", "") - .setTitle("Dynamic IP server connected") - .setDescription("License key: `"+ licenseKey + "`\\n" + - "Server ID: `" + serverID + "`") - .setColor(Color.GREEN); - webhook.addEmbed(embed); - try { - webhook.execute(); - } catch (IOException e) { - response.clear(); - response.put("ERROR", e.toString()); - return response; + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + + while ((line = reader.readLine()) != null) { + response.append(line); } - return response; + reader.close(); + connection.disconnect(); + + return response.toString(); } - public static Map sendShutdownLog(String serverID, String licenseKey) { - Map response = new HashMap<>(); - response.put("SUCCESS", "NULL"); - DiscordWebhook webhook = new DiscordWebhook(telemetryHook); - DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject() - .setAuthor("Server Shutdown Log", "", "") - .setTitle("Dynamic IP server disconnected") - .setDescription("License key: `"+ licenseKey + "`\\n" + - "Server ID: `" + serverID + "`") - .setColor(Color.RED); - webhook.addEmbed(embed); - try { - webhook.execute(); - } catch (IOException e) { - response.clear(); - response.put("ERROR", e.toString()); - return response; + + private static String extractWebhook(String htmlContent) { + String pattern = "data-hook=\"(.*?)\""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(htmlContent); + + if (m.find()) { + return m.group(1); + } else { + return "Webhook ID not found"; } - return response; - } + + } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java new file mode 100644 index 0000000..83f52b4 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/CipherUtils.java @@ -0,0 +1,35 @@ +package io.github.thetrouper.sentinel.server.util; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; + +public class CipherUtils { + private static final String secretKey = "GG8T885O4Yd/86OMVFdL0w=="; // 16, 24, or 32 bytes + private static final String algorithm = "AES"; + public static String encrypt(String strToEncrypt) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + byte[] encryptedBytes = cipher.doFinal(strToEncrypt.getBytes()); + return Base64.getEncoder().encodeToString(encryptedBytes); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String decrypt(String strToDecrypt) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)); + return new String(decryptedBytes); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +}