java asm patch方法记录

背景

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