使用 Javassist 修改后检测加载 类
Instrumenting loaded classes after modification with Javassist
我有以下 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()
不会替换当前加载的 class,为了实现这一点,我需要使用 [=] 中的 Instrumentation API 19=]。但是,我没能找到太多关于如何使用 Instrumentation 的解释 API。
任何有关如何执行此操作的建议将不胜感激。
示例 javaagent 项目:java-agent-asm-javassist-sample(在 google 中找到,不是我的代码)。
为了从 Instrumentation 中获益 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'。
通过 JVM 参数传递您的 javagent:java -javaagent:some/path/agent.jar -jar your-main-app.jar
我有以下 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()
不会替换当前加载的 class,为了实现这一点,我需要使用 [=] 中的 Instrumentation API 19=]。但是,我没能找到太多关于如何使用 Instrumentation 的解释 API。
任何有关如何执行此操作的建议将不胜感激。
示例 javaagent 项目:java-agent-asm-javassist-sample(在 google 中找到,不是我的代码)。
为了从 Instrumentation 中获益 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'。
通过 JVM 参数传递您的 javagent:java -javaagent:some/path/agent.jar -jar your-main-app.jar