简体   繁体   中英

Instrumenting loaded classes after modification with Javassist

I have the following Javassist code to modify a logging method to make it only log certain cases (in an attempt to detect hackers transferring large sums of money in a game, for context):

CtClass ctClass = ClassPool.getDefault().getCtClass(Trade.class.getName());
CtMethod commandMethod = ctClass.getDeclaredMethod("log");
commandMethod.setBody("if (/* conditions */) {"
                    + "    fw.write(sender + \" [\" + senderUser.getMoney() + \"/\" + senderOldBal + \"] sent \" + pay.getMoney() + \" to \" + receiver + \"[\" + receiverOldBal + \"/\" + receiverUser.getMoney() + \"]\");"
                    + "}");

I understand that simply calling ctClass.toClass() will not replace the currently loaded class, and that in order to achieve this I need to make use of the Instrumentation API in Java. However I have not been able to find much in the way of explanations of how to use the Instrumentation API.

Any advice on how to do this would be appreciated.

Sample javaagent project: java-agent-asm-javassist-sample (found in google, not my code).

In order to benefit from Instrumentation API you need to build your own javaagent:

public class Agent {

    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader classLoader, String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
                if ("your/package/Trade".equals(s)) {
                    try {
                        ClassPool cp = ClassPool.getDefault();
                        CtClass ctClass = cp.get("your.package.Trade");
                        CtMethod commandMethod = ctClass.getDeclaredMethod("log");
                        commandMethod.setBody("if (/* conditions */) {"
                            + "    fw.write(sender + \" [\" + senderUser.getMoney() + \"/\" + senderOldBal + \"] sent \" + pay.getMoney() + \" to \" + receiver + \"[\" + receiverOldBal + \"/\" + receiverUser.getMoney() + \"]\");"
                            + "}");
                        byte[] byteCode = ctClass.toBytecode();
                        ctClass.detach();
                        return byteCode;
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                return null;
            }
        });
    }

}

Compile it and package into agent.jar with 'Premain-Class' in manifest.

Pass your javagent via JVM argument: java -javaagent:some/path/agent.jar -jar your-main-app.jar

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM