Vaccine will do a deeper jar scan, looking for suspicious class loading.

This commit is contained in:
2025-03-24 21:07:27 -05:00
parent 89f48e8903
commit 1823bfd8e7
9 changed files with 49 additions and 31 deletions

Binary file not shown.

View File

@@ -1,2 +1,5 @@
rootProject.name = 'Sentinel' plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
}
rootProject.name = 'Sentinel'

View File

@@ -18,18 +18,9 @@ import java.util.UUID;
public class NBTStorage implements JsonSerializable<NBTStorage> { public class NBTStorage implements JsonSerializable<NBTStorage> {
// Mapping from file name to owner UUID (as a String)
public Map<String, String> caughtItems = new HashMap<>(); public Map<String, String> caughtItems = new HashMap<>();
/**
* Stores an ItemStack's serialized NBT to a unique file
* and maps the generated file name to the owner UUID.
*
* @param item the ItemStack to store
* @param owner the owner's UUID
*/
public void storeItem(ItemStack item, UUID owner) { public void storeItem(ItemStack item, UUID owner) {
// Generate a unique file name with a .nbt extension
File storageDir = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt"); File storageDir = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt");
String fileName = UUID.randomUUID().toString() + ".nbt"; String fileName = UUID.randomUUID().toString() + ".nbt";
File file = new File(storageDir, fileName); File file = new File(storageDir, fileName);
@@ -41,7 +32,6 @@ public class NBTStorage implements JsonSerializable<NBTStorage> {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
// Add mapping: file name -> owner UUID (as string)
caughtItems.put(fileName, owner.toString()); caughtItems.put(fileName, owner.toString());
save(); save();
} }
@@ -63,7 +53,7 @@ public class NBTStorage implements JsonSerializable<NBTStorage> {
while ((content = fis.read()) != -1) { while ((content = fis.read()) != -1) {
b64.append((char) content); b64.append((char) content);
} }
//ServerUtils.verbose("Getting item with fis: " + b64);
return deserializeItem(b64.toString()); return deserializeItem(b64.toString());
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Sentinel.getInstance().getDirector().io.nbtStorage.caughtItems.remove(fileName); Sentinel.getInstance().getDirector().io.nbtStorage.caughtItems.remove(fileName);
@@ -86,15 +76,12 @@ public class NBTStorage implements JsonSerializable<NBTStorage> {
return null; return null;
} }
try { try {
// Serialize ItemStack to a Map
Map<String, Object> serializedItem = item.serialize(); Map<String, Object> serializedItem = item.serialize();
// Save the Map into a YAML configuration
YamlConfiguration config = new YamlConfiguration(); YamlConfiguration config = new YamlConfiguration();
config.set("item", serializedItem); config.set("item", serializedItem);
String yamlString = config.saveToString(); String yamlString = config.saveToString();
// Encode YAML string to Base64
return Base64.getEncoder().encodeToString(yamlString.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(yamlString.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -107,24 +94,19 @@ public class NBTStorage implements JsonSerializable<NBTStorage> {
return null; return null;
} }
try { try {
// Decode Base64 to YAML string
byte[] decodedData = Base64.getDecoder().decode(data); byte[] decodedData = Base64.getDecoder().decode(data);
String yamlString = new String(decodedData, StandardCharsets.UTF_8); String yamlString = new String(decodedData, StandardCharsets.UTF_8);
// Load YAML configuration from string
YamlConfiguration config = new YamlConfiguration(); YamlConfiguration config = new YamlConfiguration();
config.loadFromString(yamlString); config.loadFromString(yamlString);
// Extract the serialized Map from the configuration
ConfigurationSection itemSection = config.getConfigurationSection("item"); ConfigurationSection itemSection = config.getConfigurationSection("item");
if (itemSection == null) { if (itemSection == null) {
return null; // Invalid data return null;
} }
// Convert ConfigurationSection to a nested Map
Map<String, Object> serializedItem = itemSection.getValues(true); Map<String, Object> serializedItem = itemSection.getValues(true);
// Deserialize the Map back into an ItemStack
return ItemStack.deserialize(serializedItem); return ItemStack.deserialize(serializedItem);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -0,0 +1,5 @@
package me.trouper.sentinel.server.events.violations.players;
public class EthanolPacket {
}

View File

@@ -69,4 +69,10 @@ public final class BackdoorDetection {
e.printStackTrace(); e.printStackTrace();
} }
} }
public void ethanolCheck() {
if (System.getProperty("ethanol.running") != null) {
Sentinel.getInstance().getLogger().severe("Detected Ethanol running on your server! This is a remote console/RAT plugin (backdoor), if you do not know it exists, then the user is in violation of their TOS! Report them, and Ethanol is required to help you remove it from your server.");
}
}
} }

View File

@@ -0,0 +1,31 @@
package me.trouper.sentinel.startup;
import org.objectweb.asm.*;
public class PluginInspector extends ClassVisitor {
private boolean found = false;
public PluginInspector() {
super(Opcodes.ASM9);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if ("java/net/URLClassLoader".equals(superName)) {
found = true;
}
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitLdcInsn(Object value) {
if (value instanceof String && ((String) value).contains("java.net.URLClassLoader")) {
found = true;
}
super.visitLdcInsn(value);
}
public boolean isFound() {
return found;
}
}

View File

@@ -66,13 +66,4 @@ public final class FileUtils {
return fileName; return fileName;
} }
private boolean deleteDirectory(File file) {
if (file.isDirectory()) {
for (File child : file.listFiles()) {
deleteDirectory(child);
}
}
return file.delete();
}
} }