This commit is contained in:
samczsun 2016-10-19 17:44:33 -04:00
parent 77f1f18f27
commit ece4416c2e
9 changed files with 198 additions and 94 deletions

View File

@ -1,5 +1,34 @@
package mineplex.core.antihack; package mineplex.core.antihack;
import javax.xml.bind.DatatypeConverter;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import net.minecraft.server.v1_8_R3.ChatClickable;
import net.minecraft.server.v1_8_R3.ChatComponentText;
import net.minecraft.server.v1_8_R3.ChatHoverable;
import net.minecraft.server.v1_8_R3.ChatModifier;
import net.minecraft.server.v1_8_R3.EnumChatFormat;
import net.minecraft.server.v1_8_R3.IChatBaseComponent;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent;
import org.bukkit.plugin.ServicePriority;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -44,34 +73,9 @@ import mineplex.core.punish.Category;
import mineplex.core.punish.Punish; import mineplex.core.punish.Punish;
import mineplex.core.punish.PunishClient; import mineplex.core.punish.PunishClient;
import mineplex.core.punish.Punishment; import mineplex.core.punish.Punishment;
import mineplex.core.punish.PunishmentResponse;
import mineplex.serverdata.commands.ServerCommandManager; import mineplex.serverdata.commands.ServerCommandManager;
import net.minecraft.server.v1_8_R3.ChatClickable;
import net.minecraft.server.v1_8_R3.ChatComponentText;
import net.minecraft.server.v1_8_R3.ChatHoverable;
import net.minecraft.server.v1_8_R3.ChatModifier;
import net.minecraft.server.v1_8_R3.EnumChatFormat;
import net.minecraft.server.v1_8_R3.IChatBaseComponent;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent;
import org.bukkit.plugin.ServicePriority;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@ReflectivelyCreateMiniPlugin @ReflectivelyCreateMiniPlugin
public class AntiHack extends MiniPlugin public class AntiHack extends MiniPlugin
{ {
@ -90,6 +94,8 @@ public class AntiHack extends MiniPlugin
public static final CheckThresholds UNKNOWN_TYPE = new CheckThresholds("Unknown", 0, Integer.MAX_VALUE, Integer.MAX_VALUE); public static final CheckThresholds UNKNOWN_TYPE = new CheckThresholds("Unknown", 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
public static final int ID_LENGTH = 5;
public static final String NAME = "Chiss"; public static final String NAME = "Chiss";
public static final String USER_HAS_BEEN_BANNED = F.main("GWEN", "%s has been banned. I am always watching."); public static final String USER_HAS_BEEN_BANNED = F.main("GWEN", "%s has been banned. I am always watching.");
public static final String USER_HAS_BEEN_BANNED_BANWAVE = USER_HAS_BEEN_BANNED; public static final String USER_HAS_BEEN_BANNED_BANWAVE = USER_HAS_BEEN_BANNED;
@ -188,22 +194,37 @@ public class AntiHack extends MiniPlugin
} }
} }
public void doBan(Player player, String message) public void doBan(Player player)
{ {
runSync(() -> runSync(() ->
{ {
CoreClient coreClient = _clientManager.Get(player); CoreClient coreClient = _clientManager.Get(player);
Consumer<Consumer<PunishmentResponse>> doPunish = after ->
{
String id = generateId(ID_LENGTH);
String finalMessage = "[GWEN] " + id + "";
require(AntihackLogger.class).save(player, id, () ->
{
require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, finalMessage, AntiHack.NAME, 3, true, -1, true, after);
});
};
if (coreClient.GetRank().has(Rank.TWITCH)) if (coreClient.GetRank().has(Rank.TWITCH))
{ {
require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, 3, true, -1, true); doPunish.accept(null);
} }
else else
{ {
runBanAnimation(player, () -> runBanAnimation(player, () ->
{ {
require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, 3, true, -1, true); doPunish.accept(result ->
{
if (result == PunishmentResponse.Punished)
{
announceBan(player); announceBan(player);
}
});
}); });
} }
}); });
@ -635,4 +656,11 @@ public class AntiHack extends MiniPlugin
) )
); );
} }
public static String generateId(int length)
{
byte[] holder = new byte[length];
ThreadLocalRandom.current().nextBytes(holder);
return DatatypeConverter.printHexBinary(holder);
}
} }

View File

@ -18,14 +18,12 @@ public abstract class AntiHackAction implements Listener
private static final Map<Class<?>, AntiHackAction> ACTIONS = new HashMap<>(); private static final Map<Class<?>, AntiHackAction> ACTIONS = new HashMap<>();
private static final AntiHackAction NOOP_ACTION = new NoopAction(); private static final AntiHackAction NOOP_ACTION = new NoopAction();
private static final Date NEXT_BAN_WAVE = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5));
static static
{ {
// ACTIONS.put(KillauraTypeA.class, new ImmediateBanAction(200)); ACTIONS.put(KillauraTypeA.class, new ImmediateBanAction(200));
// ACTIONS.put(KillauraTypeD.class, new BanwaveAction(2000)); ACTIONS.put(KillauraTypeD.class, new BanwaveAction(2000));
// ACTIONS.put(Glide.class, new ImmediateBanAction(10000)); ACTIONS.put(Glide.class, new ImmediateBanAction(10000));
// ACTIONS.put(Speed.class, new ImmediateBanAction(10000)); ACTIONS.put(Speed.class, new ImmediateBanAction(10000));
} }
private int _vl; private int _vl;

View File

@ -27,7 +27,6 @@ class BanwaveAction extends AntiHackAction
event.getPlayer(), event.getPlayer(),
banTime, banTime,
event.getCheckClass(), event.getCheckClass(),
"[GWEN] Hacking [BanWave]",
event.getViolations(), event.getViolations(),
UtilServer.getServerName() UtilServer.getServerName()
); );

View File

@ -17,12 +17,7 @@ class ImmediateBanAction extends AntiHackAction
{ {
if (event.getViolations() >= this.getMinVl()) if (event.getViolations() >= this.getMinVl())
{ {
String server = UtilServer.getServerName(); Managers.get(AntiHack.class).doBan(event.getPlayer());
if (server.contains("-"))
{
server = server.substring(0, server.indexOf('-'));
}
Managers.get(AntiHack.class).doBan(event.getPlayer(), "[GWEN] Hacking [" + server + "]");
} }
} }
} }

View File

@ -1,10 +1,14 @@
package mineplex.core.antihack.banwave; package mineplex.core.antihack.banwave;
import java.util.UUID;
import mineplex.core.MiniPlugin; import mineplex.core.MiniPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin; import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.account.CoreClient; import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager; import mineplex.core.account.CoreClientManager;
import mineplex.core.antihack.AntiHack; import mineplex.core.antihack.AntiHack;
import mineplex.core.antihack.logging.AntihackLogger;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
@ -39,23 +43,23 @@ public class BanWaveManager extends MiniPlugin
}); });
} }
public void insertBanWaveInfo(Player player, long timeToBan, Class<?> checkClass, String message, int vl, String server) public void insertBanWaveInfo(Player player, long timeToBan, Class<?> checkClass, int vl, String server)
{ {
insertBanWaveInfo(player, timeToBan, checkClass, message, vl, server, null); insertBanWaveInfo(player, timeToBan, checkClass, vl, server, null);
} }
public void insertBanWaveInfo(Player player, long timeToBan, Class<?> checkClass, String message, int vl, String server, Runnable after) public void insertBanWaveInfo(Player player, long timeToBan, Class<?> checkClass, int vl, String server, Runnable after)
{ {
runAsync(() -> runAsync(() ->
{ {
String id = AntiHack.generateId(AntiHack.ID_LENGTH);
String newMessage = "[GWEN] [BanWave] " + id + "";
CoreClient client = require(CoreClientManager.class).Get(player); CoreClient client = require(CoreClientManager.class).Get(player);
this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, checkClass.getName(), message, vl, server); this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, checkClass.getName(), newMessage, vl, server);
if (after != null) require(AntihackLogger.class).save(player, id, after);
{
after.run();
}
}); });
} }
} }

View File

@ -1,5 +1,7 @@
package mineplex.core.antihack.logging; package mineplex.core.antihack.logging;
import javax.xml.bind.DatatypeConverter;
import com.mineplex.anticheat.checks.Check; import com.mineplex.anticheat.checks.Check;
import com.mineplex.anticheat.checks.CheckManager; import com.mineplex.anticheat.checks.CheckManager;
import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TIntObjectMap;
@ -7,25 +9,34 @@ import gnu.trove.map.TIntObjectMap;
import mineplex.core.antihack.ViolationLevels; import mineplex.core.antihack.ViolationLevels;
import mineplex.core.database.MinecraftRepository; import mineplex.core.database.MinecraftRepository;
import mineplex.serverdata.database.DBPool; import mineplex.serverdata.database.DBPool;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.ByteArrayInputStream;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
public class AnticheatDatabase extends MinecraftRepository public class AnticheatDatabase extends MinecraftRepository
{ {
//CREATE TABLE IF NOT EXISTS user_anticheat_vls (accountId INT, checkId INT, maxViolations INT, totalAlerts INT, PRIMARY KEY(accountId, checkId)); /*
CREATE TABLE IF NOT EXISTS anticheat_vl_logs (accountId INT, checkId INT, maxViolations INT, totalAlerts INT, PRIMARY KEY(accountId, checkId));
CREATE TABLE IF NOT EXISTS anticheat_ban_metadata (id INT NOT NULL AUTO_INCREMENT, accountId INT, banId CHAR(10) NOT NULL, data MEDIUMTEXT NOT NULL, PRIMARY KEY(id));
*/
public static final String INSERT_INTO_BAN_LOG = "INSERT INTO user_anticheat_bans (accountId, banId, data) VALUES (?, ?, ?)"; public static final String INSERT_INTO_BAN_LOG = "INSERT INTO anticheat_vl_logs (accountId, banId, data) VALUES (?, ?, ?)";
public static final String UPDATE_VIOLATIONS = "INSERT INTO user_anticheat_vls (accountId, checkId, " public static final String INSERT_INTO_METADATA = "INSERT INTO anticheat_ban_metadata (accountId, banId, data) VALUES (?, ?, ?)";
public static final String UPDATE_VIOLATIONS = "INSERT INTO anticheat_vl_logs (accountId, checkId, "
+ "maxViolations, totalAlerts) VALUES (?, ?, ?, ?) ON DUPLICATE KEY" + "maxViolations, totalAlerts) VALUES (?, ?, ?, ?) ON DUPLICATE KEY"
+ " UPDATE maxViolations = VALUES(maxViolations), totalAlerts = VALUES(totalAlerts);"; + " UPDATE maxViolations = VALUES(maxViolations), totalAlerts = VALUES(totalAlerts);";
private static final String GET_VLS = "SELECT checkId, maxViolations, totalAlerts FROM user_anticheat_vls"; private static final String GET_VLS = "SELECT checkId, maxViolations, totalAlerts FROM anticheat_vl_logs";
private static final String GET_VLS_BY_ACCOUNT_ID = GET_VLS + " WHERE accountId = ?"; private static final String GET_VLS_BY_ACCOUNT_ID = GET_VLS + " WHERE accountId = ?";
@ -132,6 +143,26 @@ public class AnticheatDatabase extends MinecraftRepository
return Optional.ofNullable(levels); return Optional.ofNullable(levels);
} }
public void saveMetadata(int accountId, String id, String base64, Runnable after)
{
try (Connection connection = getConnection())
{
PreparedStatement statement = connection.prepareStatement(INSERT_INTO_METADATA);
statement.setInt(1, accountId);
statement.setString(2, id);
statement.setString(3, base64);
statement.executeUpdate();
if (after != null)
after.run();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
}
@Override @Override
protected void initialize() protected void initialize()
{ {

View File

@ -5,8 +5,10 @@ import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -14,11 +16,13 @@ import java.util.UUID;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.tukaani.xz.LZMA2Options; import org.tukaani.xz.LZMA2Options;
import org.tukaani.xz.UnsupportedOptionsException;
import org.tukaani.xz.XZ; import org.tukaani.xz.XZ;
import org.tukaani.xz.XZOutputStream; import org.tukaani.xz.XZOutputStream;
@ -30,9 +34,15 @@ import com.mineplex.anticheat.checks.Check;
import mineplex.core.MiniPlugin; import mineplex.core.MiniPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin; import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.account.CoreClientManager; import mineplex.core.account.CoreClientManager;
import mineplex.core.antihack.AntiHack;
import mineplex.core.antihack.ViolationLevels; import mineplex.core.antihack.ViolationLevels;
import mineplex.core.antihack.logging.builtin.ServerInfoMetadata; import mineplex.core.antihack.logging.builtin.ServerInfoMetadata;
import mineplex.core.antihack.logging.builtin.ViolationInfoMetadata; import mineplex.core.antihack.logging.builtin.ViolationInfoMetadata;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TIntObjectHashMap;
@ -83,6 +93,36 @@ public class AntihackLogger extends MiniPlugin
pushQueuedViolationChanges(); pushQueuedViolationChanges();
} }
@EventHandler
public void addCommands()
{
if (UtilServer.isTestServer())
{
addCommand(new CommandBase<AntihackLogger>(this, Rank.DEVELOPER, "savemetadata")
{
@Override
public void Execute(Player caller, String[] args)
{
if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
{
if (args.length == 1)
{
Player player = Bukkit.getPlayer(args[0]);
if (player != null)
{
String id = AntiHack.generateId(AntiHack.ID_LENGTH);
save(player, id, () ->
{
UtilPlayer.message(caller, F.main(getName(), "Saved metadata for " + player.getName() + " with id " + id));
});
}
}
}
}
});
}
}
private void pushQueuedViolationChanges() private void pushQueuedViolationChanges()
{ {
TIntObjectMap<ViolationLevels> ret; TIntObjectMap<ViolationLevels> ret;
@ -200,47 +240,20 @@ public class AntihackLogger extends MiniPlugin
runAsync(() -> _db.saveViolationLevels(queue)); runAsync(() -> _db.saveViolationLevels(queue));
} }
_metadata.values().forEach(metadata -> metadata.remove(event.getPlayer().getUniqueId()));
}
public void save(Player player, String id, Runnable after)
{
runAsync(() ->
{
JsonObject info = new JsonObject(); JsonObject info = new JsonObject();
for (AnticheatMetadata anticheatMetadata : _metadata.values()) for (AnticheatMetadata anticheatMetadata : _metadata.values())
{ {
info.add(anticheatMetadata.getId(), anticheatMetadata.build(event.getPlayer().getUniqueId()));
anticheatMetadata.remove(event.getPlayer().getUniqueId());
}
try try
{ {
byte[] b = GSON.toJson(info).getBytes(StandardCharsets.UTF_8); info.add(anticheatMetadata.getId(), anticheatMetadata.build(player.getUniqueId()));
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
File out = new File(event.getPlayer().getName() + ".xz");
out.createNewFile();
FileOutputStream fout = new FileOutputStream(out);
long start = System.currentTimeMillis();
XZOutputStream o2 = new XZOutputStream(bout, new LZMA2Options(LZMA2Options.PRESET_MIN), XZ.CHECK_NONE);
o2.write(b);
o2.close();
long end = System.currentTimeMillis();
System.out.println("Took " + (end - start) + "ms");
fout.write(bout.toByteArray());
fout.close();
File out1 = new File(event.getPlayer().getName() + ".base64");
out1.createNewFile();
FileOutputStream fout1 = new FileOutputStream(out1);
fout1.write(DatatypeConverter.printBase64Binary(bout.toByteArray()).getBytes(StandardCharsets.UTF_8));
fout1.close();
}
File out1 = new File(event.getPlayer().getName() + ".txt");
out1.createNewFile();
FileOutputStream o1 = new FileOutputStream(out1);
o1.write(b);
o1.close();
} }
catch (Throwable t) catch (Throwable t)
{ {
@ -248,6 +261,30 @@ public class AntihackLogger extends MiniPlugin
} }
} }
String str = GSON.toJson(info);
byte[] b = str.getBytes(StandardCharsets.UTF_8);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try
{
XZOutputStream o2 = new XZOutputStream(bout, new LZMA2Options(LZMA2Options.PRESET_MIN), XZ.CHECK_NONE);
o2.write(b);
o2.close();
}
catch (IOException ex)
{
// Should never happen
ex.printStackTrace();
}
byte[] compressed = bout.toByteArray();
String base64 = Base64.getEncoder().encodeToString(compressed);
_db.saveMetadata(_clientManager.getAccountId(player), id, base64, after);
});
}
public void registerMetadata(AnticheatMetadata metadata) public void registerMetadata(AnticheatMetadata metadata)
{ {
if (!this._metadata.containsKey(metadata.getId())) if (!this._metadata.containsKey(metadata.getId()))

View File

@ -1,7 +1,7 @@
package mineplex.core.punish; package mineplex.core.punish;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.function.Consumer;
import java.util.logging.Level; import java.util.logging.Level;
import mineplex.core.account.CoreClient; import mineplex.core.account.CoreClient;
@ -170,6 +170,11 @@ public class Punish extends MiniPlugin
} }
public void AddPunishment(String playerName, final Category category, final String reason, String callerName, final int severity, boolean ban, long duration, final boolean silent) public void AddPunishment(String playerName, final Category category, final String reason, String callerName, final int severity, boolean ban, long duration, final boolean silent)
{
AddPunishment(playerName, category, reason, callerName, severity, ban, duration, silent, null);
}
public void AddPunishment(String playerName, final Category category, final String reason, String callerName, final int severity, boolean ban, long duration, final boolean silent, Consumer<PunishmentResponse> callback)
{ {
Player player = Bukkit.getPlayerExact(playerName); Player player = Bukkit.getPlayerExact(playerName);
if (player != null) if (player != null)
@ -335,6 +340,10 @@ public class Punish extends MiniPlugin
}); });
} }
} }
if (callback != null)
{
callback.accept(banResult);
}
} }

View File

@ -179,10 +179,13 @@ public class GameInfoMetadata extends AnticheatMetadata
Map<String, Integer> stats = game.GetStats().get(player); Map<String, Integer> stats = game.GetStats().get(player);
if (stats != null)
{
JsonObject statsObject = new JsonObject(); JsonObject statsObject = new JsonObject();
stats.forEach(statsObject::addProperty); stats.forEach(statsObject::addProperty);
gameObj.add(KEY_STATS, statsObject); gameObj.add(KEY_STATS, statsObject);
}
gameObj.addProperty(KEY_WINNER, game.Winner); gameObj.addProperty(KEY_WINNER, game.Winner);
} }