初识Javassist-修改函数内容
前言
上一篇文章我们能够在main函数之前加载premain函数了,那么我们是否可以利用这个特性来对函数内容进行修改呢
实现
1 2 3 4 5 6 7 8 9 10 11
| public class Test { public static void main(String[] args){ System.out.println("test123"); new Sayhello().sayhello(); } public void doSomething(){ System.out.println("do Something test"); } }
|
1 2 3 4 5 6
| public class Sayhello { public void sayhello(){ System.out.println("hello"); } }
|
正常运行效果
那么假如攻击者要利用main函数里面的某些逻辑实现攻击,我们就可以在执行main函数之前修改main函数的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.l1m3.premainagent.demo; import javassist.*;
import java.io.IOException; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain;
public class PremainAgent { public static void premain(String arg, Instrumentation instrumentation) { System.err.println("agent startup , args is " + arg); Class<?>[] cLasses = instrumentation.getAllLoadedClasses(); for (Class<?> cls : cLasses) {
} instrumentation.addTransformer(new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className!=null&&className.replaceAll("/", ".").equals("Test") ){ ClassPool pool = new ClassPool(); pool.insertClassPath(new LoaderClassPath(loader)); try { System.out.println("执行 增加函数"); CtClass ctClass = pool.get(className.replaceAll("/", "\\.")); CtMethod ctMethod = ctClass.getDeclaredMethod("main"); CtMethod[] arrays = ctClass.getDeclaredMethods(); for(int i=0;i<arrays.length;i++) { System.out.println(arrays[i]); }
ctMethod.setBody("{\n" + " Runtime runtime = Runtime.getRuntime();\n" + " runtime.exec(\"curl 120.79.197.4:82\");\n" + " }"); ctMethod.insertBefore("System.out.println(System.currentTimeMillis());");
return ctClass.toBytecode(); } catch (NotFoundException e) { e.printStackTrace(); } catch (CannotCompileException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
} return null; } }); }
}
|
设置vmoption后执行,效果如下
当然这一切都是为了将来想自己写的小型RASP作准备的,针对不同的漏洞hook不同的类/方法,如何处理函数,以及后续升级都是一段很长的路,简单看过OPENRASP后发现他是利用js来加规则的,我觉得这个特性很有亮点。