在调用get方法后又回到了前面说到的地方,这里就会去调用transform方法去完成后面的命令执行。这里先不细说。
在分析完POC代码后其实并没有去看到一个完整的调用链,这里有必要去调试一遍。
0x03 CC3链调试先在AnnotationInvocationHandler的readobject方法中去打个断点进行调试分析
在这里可以看到这里的this.memberValues的值为被代理的lazyMap的对象,调用了lazyMap的entrySet方法。那么这时候被代理对象的调用处理器的invoke方法会执行。前面说过使用的AnnotationInvocationHandler作为调用处理器,这里调用的就是AnnotationInvocationHandler的invoke方法,跟进一下invoke方法。
invoke方法在内部调用了lazyMap的get方法,再来跟进一下get方法
到这里其实就能看到了 this.factory.transform(key);,调用了transform方法,在这里的this.factory为ChainedTransformer的实例化对象。再来跟进一下transform方法就能看到ChainedTransformer的transform内部的调用结构。
在POC构造的时候为ChainedTransformer这个对象传入了一个数组,数组的第一值为ConstantTransformer实例化对象,第二个为InstantiateTransformer实例化对象。
所以在这里第一次遍历this.iTransformers[i]的值为ConstantTransformer。ConstantTransformer的transform会直接返回传入的对象。在POC代码构造的时候,传入的是TrAXFilter对象,所以在这里会直接进行返回TrAXFilter,并且会作为第二次遍历的传参值。
而在第二次遍历的时候,this.iTransformers[i]的值为InstantiateTransformer的实例化对象。所以调用的是InstantiateTransformer的transform方法并且传入了TrAXFilter对象。跟进一下InstantiateTransformer的transform方法。
这里其实是比较有意思的,刚刚传入的是TrAXFilter对象,所以这里的input为TrAXFilter,this.iParamTypes为Templates,this.iArgs为构造好的恶意TemplatesImpl实例化对象。(这里之所以说他是恶意的TemplatesImpl对象是因为在前面使用反射将他的_bytecodes设置成了一个使用javassist动态创建的恶意类的字节码)
该transform方法中使用getConstructor方法获取TrAXFilter参数为Templates的构造方法。
使用该构造方法创建一个对象,并且传入恶意的TemplatesImpl实例化对象。在该构造方法当中会调用TemplatesImpl的newTransformer方法。跟进一下newTransformer方法。
newTransformer方法内部调用了getTransletInstance方法再跟进一下。
这里可以看到先是判断了_name的值是否为空,为空的话就会执行返回null,不向下执行。这也是前面为什么使用反射获取并且修改_name值的原因。
下面一步是判断_class是否为空,显然我们这里的_class值是null,这时候就会调用defineTransletClasses方法,跟进一下。