背景
审计某个代码的时候,有一个激活状态的验证写在一个全局的filter里,如果没有激活则将会直接返回空,功能无法调试。功能实现在jar包里,项目依赖很多,重新打jar包有点麻烦,直接用asm库做个java agent,在目标filter类加载的时候,将监测的Method重写,直接覆盖为return true;。感觉通用性还可以,记录一下,免得以后用的时候找不到。
import jdk.internal.org.objectweb.asm.*;
import jdk.internal.org.objectweb.asm.ClassReader;
import java.io.PrintStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst){
System.out.println("premainAgent Start");
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
className = className.replace("/", ".");
if (className.equals("xxxxx.xxxxx.xxxxxx.TargetFilter")) {
System.out.println("Found it !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
System.out.println("PremainAgent get onload class : " + className);
ClassReader classReader = new ClassReader(classfileBuffer);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
System.out.println("PremainAgent get signature : " + signature);
System.out.println("PremainAgent get Method : " + name);
System.out.println("PremainAgent get desc : " + desc);
System.out.println("PremainAgent get exceptions : " + exceptions);
if (("targetMethodName".equals(name)) && ("(Ljavax/servlet/http/HttpServletRequest;)Z").equals(desc)){
System.out.println("Find target Method : " + name + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
return new MethodVisitor(Opcodes.ASM5, mv) {
@Override
public void visitCode() {
mv.visitCode();
mv.visitFieldInsn(Opcodes.GETSTATIC,
Type.getInternalName(System.class),
"out",
Type.getDescriptor(PrintStream.class));
mv.visitLdcInsn("目标方法即将运行");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(PrintStream.class), //"java/io/PrintStream"
"println",
"(Ljava/lang/String;)V",//方法描述符
false);
mv.visitLdcInsn(true);
mv.visitInsn(IRETURN);
mv.visitEnd();
super.visitCode();
}
};
}
return mv;
}
};
classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
classfileBuffer = classWriter.toByteArray();
}
return classfileBuffer;
}
});
}
public static void agentmain(String agentArgs, Instrumentation inst){
System.out.println("agentmainAgent Start");
}
}