raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.22k stars 799 forks source link

not able to intercept java.lang package #1690

Open sagarvyass opened 1 month ago

sagarvyass commented 1 month ago

not able to intercept java.lang.Runtime

package com.security.aspect_example;

import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.utility.JavaModule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import java.io.File;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;

import java.io.File;
import java.lang.instrument.Instrumentation;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.concurrent.Callable;

public class AspectExampleApplication {

    public static void main(String[] args) throws Exception {
        premain(null, ByteBuddyAgent.install());
        Runtime.getRuntime().exec("ls");

    }

    public static void premain(String arg, Instrumentation inst) throws Exception {
        File temp = Files.createTempDirectory("tmp").toFile();
        ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, inst).inject(Collections.singletonMap(
                new TypeDescription.ForLoadedType(MyInterceptor.class),
                ClassFileLocator.ForClassLoader.read(MyInterceptor.class)));
        new AgentBuilder.Default()
                .ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))

                .type(ElementMatchers.nameEndsWith("java.lang.Runtime"))
                .transform(new AgentBuilder.Transformer() {

                    @Override
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader,JavaModule javaModule, ProtectionDomain protectionDomain) {
                        return builder.method(ElementMatchers.named("getRuntime")).intercept(MethodDelegation.to(MyInterceptor.class));
                    }
                }).installOn(inst);
    }
    public static class MyInterceptor {

        public static String intercept(@SuperCall Callable<String> zuper) throws Exception {
            System.out.println("Intercepted!");
            return zuper.call();
        }
    }

}
raphw commented 1 month ago

You would need to enable retransformation using RetransformationStrategy.RETRANSFORM, and likely set disableClassFormatChanges(). Runtime will already be loaded when the JVM dispatches the agent.

sagarvyass commented 1 month ago

update to this, still not working

public static void premain(String arg, Instrumentation inst) throws Exception {
        File temp = Files.createTempDirectory("tmp").toFile();
        ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, inst).inject(Collections.singletonMap(
                new TypeDescription.ForLoadedType(MyInterceptor.class),
                ClassFileLocator.ForClassLoader.read(MyInterceptor.class)));
        new AgentBuilder.Default()
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .disableClassFormatChanges()
                .ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))

                .type(ElementMatchers.nameEndsWith("java.lang.Runtime"))
                .transform(new AgentBuilder.Transformer() {

                    @Override
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader,JavaModule javaModule, ProtectionDomain protectionDomain) {
                        return builder.method(ElementMatchers.named("getRuntime")).intercept(MethodDelegation.to(MyInterceptor.class));
                    }
                }).installOn(inst);
    }
    public static class MyInterceptor {

        public static String intercept(@SuperCall Callable<String> zuper) throws Exception {
            System.out.println("Intercepted!");
            return zuper.call();
        }
    }
raphw commented 1 month ago

If you add a listener, you will see an error message. With retransofation, you cannot apply all forms of transformations. You will likely need to switch over to Advice.

sagarvyass commented 1 month ago

would the advice be able to intercept core java packages like Runtime.exec() ?

raphw commented 1 month ago

Certainly.

sagarvyass commented 1 month ago

I have tried LTW using aspectJ weaver as a java agent, still couldn’t intercept. Is there some resource you could help with?

raphw commented 1 month ago

If you look up YouTube and Vimeo, I have given a row of introductions to the topic. Looking at Byte Buddy's tests is also a good option.

sagarvyass commented 1 month ago

can you please share the links?

raphw commented 1 month ago

For example: https://www.youtube.com/watch?v=o9NVLXKRKeY