Read for information...
Now using ASM manipulation to remove invalid methods on load Fixed imports Fixed Chat Components being used in 1.12 Fixed tab complete showing args for disguise options you can't use Disguise option permissions now demand a parameter to be the method name Falling block disguises are now only usable with blocks LibsDisguises command now tab completes the new options Libs Disguises command lets you create a vanilla compatible item string If a vehicle is disguised as a vehicle, don't give no gravity Fixed horse disguise using almost random values for its flagwatcher settings Renamed horse disguise setMouthOpen to setEating Slightly better string for premium info jar location Skip attributes packets if using older ProtocolLib jar Don't cancel entity death if entity is dead Improved disguise permissions checking Fixed time parameter not being attributed properly
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public class Asm13 implements IAsm {
|
||||
public Class<?> createClassWithoutMethods(String className,
|
||||
ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException, InvocationTargetException,
|
||||
IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
|
||||
ClassReader cr = new ClassReader(
|
||||
getClass().getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class"));
|
||||
ClassWriter writer = new ClassWriter(cr, 0);
|
||||
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM5, writer) {
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
|
||||
String[] exceptions) {
|
||||
|
||||
Map.Entry<String, String> entry = illegalMethods.stream()
|
||||
.filter(e -> e.getKey().equals(name) && e.getValue().equals(desc)).findFirst().orElse(null);
|
||||
|
||||
if (entry != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.visitMethod(access, name, desc, signature, exceptions);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
byte[] bytes = writer.toByteArray();
|
||||
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
Field field = loader.getClass().getDeclaredField("classes");
|
||||
field.setAccessible(true);
|
||||
Map<String, Class<?>> map = (Map<String, Class<?>>) field.get(loader);
|
||||
Class newClass =
|
||||
|
||||
(Class<?>) getDefineClassMethod()
|
||||
.invoke(getClass().getClassLoader(), className, bytes, 0, bytes.length);
|
||||
|
||||
map.put(className, newClass);
|
||||
return newClass;
|
||||
}
|
||||
|
||||
private static Method getDefineClassMethod() throws NoSuchMethodException {
|
||||
Method defineClass = ClassLoader.class
|
||||
.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
|
||||
defineClass.setAccessible(true);
|
||||
|
||||
return defineClass;
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public class Asm14 implements IAsm {
|
||||
public Class<?> createClassWithoutMethods(String className,
|
||||
ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException, InvocationTargetException,
|
||||
IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
|
||||
ClassReader cr = new ClassReader(
|
||||
getClass().getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class"));
|
||||
ClassWriter writer = new ClassWriter(cr, 0);
|
||||
|
||||
cr.accept(new ClassVisitor(Opcodes.ASM5, writer) {
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
|
||||
String[] exceptions) {
|
||||
|
||||
Map.Entry<String, String> entry = illegalMethods.stream()
|
||||
.filter(e -> e.getKey().equals(name) && e.getValue().equals(desc)).findFirst().orElse(null);
|
||||
|
||||
if (entry != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.visitMethod(access, name, desc, signature, exceptions);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
byte[] bytes = writer.toByteArray();
|
||||
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
Field field = loader.getClass().getDeclaredField("classes");
|
||||
field.setAccessible(true);
|
||||
Map<String, Class<?>> map = (Map<String, Class<?>>) field.get(loader);
|
||||
Class newClass =
|
||||
|
||||
(Class<?>) getDefineClassMethod()
|
||||
.invoke(getClass().getClassLoader(), className, bytes, 0, bytes.length);
|
||||
|
||||
map.put(className, newClass);
|
||||
return newClass;
|
||||
}
|
||||
|
||||
private static Method getDefineClassMethod() throws NoSuchMethodException {
|
||||
Method defineClass = ClassLoader.class
|
||||
.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
|
||||
defineClass.setAccessible(true);
|
||||
|
||||
return defineClass;
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public interface IAsm {
|
||||
public Class<?> createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,41 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
@Getter
|
||||
public class WatcherInfo {
|
||||
private int added = -1;
|
||||
private int removed = -1;
|
||||
private String watcher;
|
||||
private String method;
|
||||
private String param;
|
||||
String descriptor;
|
||||
|
||||
public WatcherInfo(String string) {
|
||||
String[] split = string.split(":", -1);
|
||||
|
||||
if (split.length > 3) {
|
||||
descriptor = split[3];
|
||||
added = Integer.parseInt(split[4]);
|
||||
removed = Integer.parseInt(split[5]);
|
||||
}
|
||||
|
||||
watcher = split[0];
|
||||
method = split[1];
|
||||
param = split[2];
|
||||
}
|
||||
|
||||
public boolean isSupported() {
|
||||
if (getAdded() >= 0 && added > ReflectionManager.getVersion().ordinal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getRemoved() < 0 || removed > ReflectionManager.getVersion().ordinal();
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public class WatcherSanitizer {
|
||||
|
||||
public static void init() {
|
||||
IAsm asm;
|
||||
|
||||
if (NmsVersion.v1_14.isSupported()) {
|
||||
asm = new Asm14();
|
||||
} else {
|
||||
asm = new Asm13();
|
||||
}
|
||||
|
||||
try (InputStream stream = LibsDisguises.getInstance().getResource("ANTI_PIRACY_ENCRYPTION")) {
|
||||
List<String> lines = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)).lines()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LinkedHashMap<String, ArrayList<Map.Entry<String, String>>> toRemove = new LinkedHashMap<>();
|
||||
|
||||
for (String s : lines) {
|
||||
WatcherInfo info = new WatcherInfo(s);
|
||||
|
||||
if (info.isSupported()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String path = "me.libraryaddict.disguise.disguisetypes." +
|
||||
(info.getWatcher().equals("FlagWatcher") ? "" : "watchers.") + info.getWatcher();
|
||||
|
||||
toRemove.putIfAbsent(path, new ArrayList<>());
|
||||
|
||||
ArrayList<Map.Entry<String, String>> list = toRemove.get(path);
|
||||
|
||||
list.add(new HashMap.SimpleEntry(info.getMethod(), info.getDescriptor()));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, ArrayList<Map.Entry<String, String>>> entry : toRemove.entrySet()) {
|
||||
Class result = asm.createClassWithoutMethods(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
catch (IOException | NoClassDefFoundError | IllegalAccessException | InvocationTargetException | NoSuchMethodException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user