如何使用Java代理拦截通过javaassist来检测java.net.Socket

问题描述 投票:0回答:1

我正在开发一个项目,需要在连接套接字后立即将一些标头写入套接字输出流。

我想在低级别拦截,例如

java.net.Socket
及其连接函数
public void connect(SocketAddress endpoint, int timeout)

变换函数如下所示

    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;
    }

我已经确认

java.net.Socket.connect()
被调用,但字节码似乎永远无法工作。我尝试在字符串中附加一些虚拟值,但仍然没有错误。

有趣的是,下面的内容适用于

java.net.SocksSocketImpl
。所以我无法弄清楚出了什么问题。

我可以在这里寻求帮助吗?

谢谢!

java sockets javassist javaagents jvm-bytecode
1个回答
0
投票

后来我自己解决了这个问题。

connect
中有多种
java.net.Socket
重载方法。在上面的代码中,我没有检查参数和方法体。所以我得到了一个只有一个参数且没有方法体的抽象方法。将字节码注入没有主体的方法会导致错误。

我最终添加了对参数编号和类型以及主体的检查,并成功地检测了该方法。

© www.soinside.com 2019 - 2024. All rights reserved.