Инструментарий загруженных классов после модификации с Javassist - PullRequest
0 голосов
/ 20 сентября 2019

У меня есть следующий код Javassist для изменения метода ведения журнала, чтобы он регистрировал только определенные случаи (в попытке обнаружить хакеров, переводящих большие суммы денег в игру, для контекста):

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() + \"]\");"
                    + "}");

Я понимаю, что простой вызов ctClass.toClass() не заменит текущий загруженный класс, и что для достижения этого мне необходимо использовать API инструментария в Java.Однако я не смог найти много объяснений о том, как использовать Instrumentation API.

Буду признателен за любые советы, как это сделать.

1 Ответ

1 голос
/ 20 сентября 2019

Пример проекта javaagent: java-agent-asm-javassist-sample (найден в Google, а не в моем коде).

Чтобы воспользоваться API инструментария, вам необходимо создать свойсобственный 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;
            }
        });
    }

}

Скомпилируйте его и упакуйте в agent.jar с 'Premain-Class' в манифесте.

Передайте свой javagent через аргумент JVM: java -javaagent:some/path/agent.jar -jar your-main-app.jar

...