背景
审计某个代码的时候,有一个激活状态的验证写在一个全局的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"); } }