mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 23:11:52 +08:00
feat: support command agent with asm on filterChain and contextValve (#51)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package com.reajason.javaweb.asm;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.bytebuddy.jar.asm.ClassReader;
|
||||
import net.bytebuddy.jar.asm.ClassVisitor;
|
||||
import net.bytebuddy.jar.asm.Opcodes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class InnerClassDiscovery {
|
||||
|
||||
/**
|
||||
* Discovers all inner classes for a given class
|
||||
*
|
||||
* @param originalClass The class to discover inner classes for
|
||||
* @return A set of fully qualified inner class names
|
||||
*/
|
||||
public static Set<String> findAllInnerClasses(Class<?> originalClass) throws IOException {
|
||||
Set<String> innerClasses;
|
||||
String resourceName = originalClass.getName().replace('.', '/') + ".class";
|
||||
try (InputStream is = originalClass.getClassLoader().getResourceAsStream(resourceName)) {
|
||||
if (is == null) {
|
||||
throw new IOException("Could not find class file for " + originalClass.getName());
|
||||
}
|
||||
|
||||
ClassReader reader = new ClassReader(is);
|
||||
InnerClassCollector collector = new InnerClassCollector(originalClass.getName());
|
||||
reader.accept(collector, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
|
||||
innerClasses = new HashSet<>(collector.getInnerClasses());
|
||||
}
|
||||
try {
|
||||
for (Class<?> innerClass : originalClass.getDeclaredClasses()) {
|
||||
innerClasses.add(innerClass.getName());
|
||||
innerClasses.addAll(findAllInnerClasses(innerClass));
|
||||
}
|
||||
} catch (SecurityException ignored) {
|
||||
}
|
||||
|
||||
return innerClasses;
|
||||
}
|
||||
|
||||
private static class InnerClassCollector extends ClassVisitor {
|
||||
private final String originalClassName;
|
||||
@Getter
|
||||
private final Set<String> innerClasses = new HashSet<>();
|
||||
|
||||
public InnerClassCollector(String originalClassName) {
|
||||
super(Opcodes.ASM9);
|
||||
this.originalClassName = originalClassName.replace('/', '.');
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
String className = name.replace('/', '.');
|
||||
if (outerName != null) {
|
||||
String outerClassName = outerName.replace('/', '.');
|
||||
if (outerClassName.equals(originalClassName)) {
|
||||
innerClasses.add(className);
|
||||
}
|
||||
} else if (className.startsWith(originalClassName + "$")) {
|
||||
innerClasses.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.reajason.javaweb.buddy;
|
||||
|
||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||
import net.bytebuddy.description.field.FieldDescription;
|
||||
import net.bytebuddy.description.field.FieldList;
|
||||
import net.bytebuddy.description.method.MethodList;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.Implementation;
|
||||
import net.bytebuddy.jar.asm.ClassVisitor;
|
||||
import net.bytebuddy.jar.asm.commons.ClassRemapper;
|
||||
import net.bytebuddy.jar.asm.commons.Remapper;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2025/3/27
|
||||
*/
|
||||
public class ClassRenameVisitorWrapper implements AsmVisitorWrapper {
|
||||
public final String originalClassName;
|
||||
public final String newClassName;
|
||||
|
||||
public ClassRenameVisitorWrapper(String originalClassName, String newClassName) {
|
||||
this.originalClassName = originalClassName.replace('.', '/');
|
||||
this.newClassName = newClassName.replace('.', '/');
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int mergeReader(int flags) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mergeWriter(int flags) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassVisitor wrap(@NotNull TypeDescription instrumentedType,
|
||||
@NotNull ClassVisitor classVisitor,
|
||||
@NotNull Implementation.Context implementationContext,
|
||||
@NotNull TypePool typePool,
|
||||
@NotNull FieldList<FieldDescription.InDefinedShape> fields,
|
||||
@NotNull MethodList<?> methods,
|
||||
int writerFlags,
|
||||
int readerFlags) {
|
||||
return new ClassRemapper(
|
||||
classVisitor,
|
||||
new Remapper() {
|
||||
@Override
|
||||
public String map(String typeName) {
|
||||
if (typeName.startsWith(originalClassName)) {
|
||||
return typeName.replaceFirst(originalClassName, newClassName);
|
||||
} else {
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user