MeowCat
MeowCat

Reputation: 23

How to use Java agent intercept to instrument java.net.Socket with javaassist

I am working on a project where I need to write some header to the socket output stream right after the socket is connected.

I want to intercept at low level such as java.net.Socket and its connect function public void connect(SocketAddress endpoint, int timeout).

The transform function looks like below

    public static byte[] transform(final ClassLoader loader, final String className, final byte[] classFileBuffer) {
        loader.loadClass(...);

        final ClassPool classPool = ClassPool.getDefault();
        classPool.appendClassPath(new LoaderClassPath(loader));
        classPool.appendSystemPath();
        classPool.importPackage(...)

        final CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classFileBuffer));

        if (className.equals("java/net/Socket")) {
            final CtMethod method = ctClass.getDeclaredMethod("connect");
            final String s = "System.out.println(\"I am in Socket.connect!\");";
            method.insertAfter(s);
            return ctClass.toBytecode();
        }
        
        return classFileBuffer;
    }

I have confirmed that java.net.Socket.connect() is called but the byte code seems to never work. I tried having some dummy in the string appended and still no error.

Interesting thing is that below works for java.net.SocksSocketImpl. So I cannot figure out what is wrong.

Can I please get some help here?

Thanks!

Upvotes: 1

Views: 73

Answers (1)

MeowCat
MeowCat

Reputation: 23

I figured out the problem myself later. There are multiple connect overloading methods in java.net.Socket. In my code above I did not check the parameters and method body. So I got an abstract method with one parameter and no method body. Injecting byte code to method without body will lead to an error.

I ended up by adding check on parameter numbers and types plus body and succeeded in instrumenting the method.

Upvotes: 0

Related Questions