Change reflection loading to replace classes in the jar loader instead, pending testing
This commit is contained in:
parent
44ab504509
commit
c8bd25ba57
@ -3,10 +3,11 @@ package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
import lombok.Getter;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
@ -15,25 +16,38 @@ import java.util.Map;
|
||||
*/
|
||||
public class Asm13 implements IAsm {
|
||||
@Getter
|
||||
private Method defineMethod;
|
||||
private final LibsJarFile libsJarFile;
|
||||
|
||||
public Asm13() throws NoSuchMethodException {
|
||||
defineMethod = getDefineClassMethod();
|
||||
public Asm13() throws Throwable {
|
||||
ClassLoader pluginClassLoader = getClass().getClassLoader();
|
||||
Class c = Class.forName("org.bukkit.plugin.java.PluginClassLoader");
|
||||
Field file = c.getDeclaredField("file");
|
||||
file.setAccessible(true);
|
||||
|
||||
libsJarFile = new LibsJarFile((File) file.get(pluginClassLoader));
|
||||
|
||||
Field field = c.getDeclaredField("jar");
|
||||
field.setAccessible(true);
|
||||
|
||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
field.set(pluginClassLoader, libsJarFile);
|
||||
}
|
||||
|
||||
public Class<?> createClassWithoutMethods(String className,
|
||||
ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException, InvocationTargetException,
|
||||
IllegalAccessException, NoSuchFieldException {
|
||||
ClassReader cr = new ClassReader(
|
||||
getClass().getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class"));
|
||||
public void createClassWithoutMethods(String className, ArrayList<Map.Entry<String, String>> illegalMethods)
|
||||
throws IOException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
|
||||
className = className.replace(".", "/") + ".class";
|
||||
|
||||
ClassReader cr = new ClassReader(getClass().getClassLoader().getResourceAsStream(className));
|
||||
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) {
|
||||
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);
|
||||
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;
|
||||
@ -43,23 +57,6 @@ public class Asm13 implements IAsm {
|
||||
}
|
||||
}, 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<?>) defineMethod.invoke(getClass().getClassLoader(), className, bytes, 0, bytes.length);
|
||||
|
||||
map.put(className, newClass);
|
||||
return newClass;
|
||||
}
|
||||
|
||||
private Method getDefineClassMethod() throws NoSuchMethodException {
|
||||
Method defineClass = ClassLoader.class
|
||||
.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
|
||||
defineClass.setAccessible(true);
|
||||
|
||||
return defineClass;
|
||||
libsJarFile.addClass(className, writer.toByteArray());
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.Map;
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
*/
|
||||
public interface IAsm {
|
||||
Class<?> createClassWithoutMethods(String className,
|
||||
void createClassWithoutMethods(String className,
|
||||
ArrayList<Map.Entry<String, String>> illegalMethods) throws IOException, InvocationTargetException,
|
||||
IllegalAccessException, NoSuchMethodException, NoSuchFieldException;
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.asm;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 15/05/2021.
|
||||
*/
|
||||
public class LibsJarFile extends JarFile {
|
||||
private final HashMap<String, byte[]> customFiles = new HashMap<>();
|
||||
|
||||
public LibsJarFile(File file) throws IOException {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized InputStream getInputStream(ZipEntry ze) throws IOException {
|
||||
if (customFiles.containsKey(ze.getName())) {
|
||||
return new ByteArrayInputStream(customFiles.get(ze.getName()));
|
||||
}
|
||||
|
||||
return super.getInputStream(ze);
|
||||
}
|
||||
|
||||
public void addClass(String name, byte[] bytes) {
|
||||
customFiles.put(name, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
customFiles.clear();
|
||||
super.close();
|
||||
}
|
||||
}
|
@ -99,10 +99,10 @@ public class WatcherSanitizer {
|
||||
}
|
||||
|
||||
for (Map.Entry<String, ArrayList<Map.Entry<String, String>>> entry : toRemove.entrySet()) {
|
||||
Class result = asm.createClassWithoutMethods(entry.getKey(), entry.getValue());
|
||||
asm.createClassWithoutMethods(entry.getKey(), entry.getValue());
|
||||
mapped.add(entry.getKey());
|
||||
}
|
||||
} catch (IOException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | NoSuchFieldException | LinkageError e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LibsDisguises.getInstance().getLogger().severe("Registered: " + new Gson().toJson(mapped));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user