From a64871dcf5f1c82e08355311fd28220b831e2f20 Mon Sep 17 00:00:00 2001 From: Taah Date: Mon, 28 Feb 2022 12:35:20 -0800 Subject: [PATCH] start patching invalid skull owners (not working rn) --- src/main/java/dev/plex/Blackout.java | 6 +- .../java/dev/plex/packet/IPacketListener.java | 16 ++++ .../dev/plex/packet/impl/SkullOwnerPatch.java | 93 +++++++++++++++++++ 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/main/java/dev/plex/packet/impl/SkullOwnerPatch.java diff --git a/src/main/java/dev/plex/Blackout.java b/src/main/java/dev/plex/Blackout.java index 4b24a77..08e670c 100644 --- a/src/main/java/dev/plex/Blackout.java +++ b/src/main/java/dev/plex/Blackout.java @@ -2,10 +2,7 @@ package dev.plex; import dev.plex.listener.PlayerListener; import dev.plex.packet.PacketManager; -import dev.plex.packet.impl.EndermanPotionPatch; -import dev.plex.packet.impl.KnowledgeBookPatch; -import dev.plex.packet.impl.LecternPatch; -import dev.plex.packet.impl.PaintingPatch; +import dev.plex.packet.impl.*; import lombok.Getter; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -35,6 +32,7 @@ public class Blackout extends JavaPlugin this.packetManager.registerListener(ServerboundUseItemOnPacket.class, new PaintingPatch()); this.packetManager.registerListener(ServerboundUseItemOnPacket.class, new LecternPatch()); this.packetManager.registerListener(ServerboundUseItemOnPacket.class, new KnowledgeBookPatch()); + this.packetManager.registerListener(ServerboundSetCreativeModeSlotPacket.class, new SkullOwnerPatch()); this.packetManager.registerListener(ClientboundUpdateMobEffectPacket.class, new EndermanPotionPatch()); this.getServer().getPluginManager().registerEvents(new PlayerListener(), this); diff --git a/src/main/java/dev/plex/packet/IPacketListener.java b/src/main/java/dev/plex/packet/IPacketListener.java index d85fdde..012c516 100644 --- a/src/main/java/dev/plex/packet/IPacketListener.java +++ b/src/main/java/dev/plex/packet/IPacketListener.java @@ -5,6 +5,8 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.world.entity.player.Player; import org.bukkit.event.Listener; +import java.lang.reflect.Field; + public interface IPacketListener> extends Listener { default boolean onReceive(Player player, T t) @@ -16,4 +18,18 @@ public interface IPacketListener> extends Listener { return Blackout.getPlugin(); } + + default J getFromField(Object object, String name) + { + try + { + Field field = object.getClass().getDeclaredField(name); + field.setAccessible(true); + return (J) field.get(object); + } catch (NoSuchFieldException | IllegalAccessException e) + { + e.printStackTrace(); + } + return null; + } } diff --git a/src/main/java/dev/plex/packet/impl/SkullOwnerPatch.java b/src/main/java/dev/plex/packet/impl/SkullOwnerPatch.java new file mode 100644 index 0000000..958d8c2 --- /dev/null +++ b/src/main/java/dev/plex/packet/impl/SkullOwnerPatch.java @@ -0,0 +1,93 @@ +package dev.plex.packet.impl; + +import com.mojang.authlib.GameProfile; +import dev.plex.Blackout; +import dev.plex.packet.IPacketListener; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Arrays; + +public class SkullOwnerPatch implements IPacketListener +{ + @EventHandler + public void onInventoryClick(InventoryClickEvent event) + { + org.bukkit.inventory.ItemStack bukkitItem = event.getCurrentItem(); + + if (bukkitItem == null) return; + + checkItem((Player) event.getWhoClicked(), bukkitItem); + } + + @EventHandler + public void onInventoryOpen(InventoryOpenEvent event) + { + if (event.getView().getType() == InventoryType.PLAYER) + { + Blackout.debug("Checking all items..."); + Arrays.stream(event.getInventory().getContents()).forEach(item -> checkItem(((CraftPlayer)event.getPlayer()).getHandle(), item)); + } + } + + @Override + public boolean onReceive(Player player, ServerboundSetCreativeModeSlotPacket serverboundSetCreativeModeSlotPacket) + { + return checkItem(player, serverboundSetCreativeModeSlotPacket.getItem().getBukkitStack()); + } + + private boolean checkItem(Player player, org.bukkit.inventory.ItemStack bukkitItem) + { + Blackout.debug("Starting skull owner exploit patch..."); + ItemStack item = ((CraftItemStack)bukkitItem).handle; + if (item.getBukkitStack().getType() != Material.PLAYER_HEAD) return true; + + SkullMeta meta = (SkullMeta) item.getBukkitStack().getItemMeta(); + GameProfile profile = getFromField(meta, "profile"); + Blackout.debug(String.valueOf(profile == null)); + if (profile == null) return true; + if (profile.getName() == null && profile.getId() == null) return true; + if (profile.getName().isEmpty()) + { + Blackout.debug("Patching invalid skull owner exploit!"); + player.getInventory().removeItem(item); + return false; + } + if (!profile.getName().matches("\\p{Alpha}")) + { + Blackout.debug("Patching invalid skull owner exploit!"); + player.getInventory().removeItem(item); + return false; + } + if (profile.getId().toString().isEmpty()) + { + Blackout.debug("Patching invalid skull owner exploit!"); + player.getInventory().removeItem(item); + return false; + } + + if (!item.hasTag()) return true; + + CompoundTag tag = item.getTag(); + if (!tag.contains("SkullOwner")) return true; + String owner = tag.getString("SkullOwner"); + if (!owner.matches("\\p{Alpha}")) + { + Blackout.debug("Patching invalid skull owner exploit!"); + player.getInventory().removeItem(item); + return false; + } + + return true; + } +}