欢迎访问本站!

首页科技正文

怎么充值usdt(www.caibao.it):JAVA平安基础(三)-- java动态署理机制

admin2021-03-05119安全技术WEB安全

USDT自动充值API接口

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

0x01 前言

在上篇文章当中,我们了解了反射的机制,可以绕过java私有接见权限检查,反射获取并挪用Runtime类执行命令执行。而Java的自带jdk动态署理机制,位于java.lang.reflect.proxy包中,其本质实现是通过反射执行invoke方式来动态获取执行方式。人人可以总结举行对比学习下。

0x02 观点

署理模式Java当中最常用的设计模式之一。其特征是署理类与委托类有同样的接口,署理类主要卖力为委托类预处置新闻、过滤新闻、把新闻转发给委托类,以及事后处置新闻等。而Java的署理机制分为静态署理和动态署理,而这里我们主要重点学习java自带的jdk动态署理机制。

0x03 静态署理示例解说

在讲动态署理之前,我们先了解下什么是静态署理。静态署理在编译使用时,界说接口或者父类,被署理工具与署理工具一起实现相同的接口或者是继续相同父类。我们用一个出租屋子作为实例解说。

界说一个接口

public interface Rental {
    public void sale();
}

委托类

// 委托类,实现接口的方式

public class Entrust implements Rental{
    @Override
    public void sale() {
        System.out.println("出租屋子");
    }
}

署理类

public class AgentRental implements Rental{
    private Rental target; // 被署理工具
    public AgentRental(Rental target) {
        this.target = target;
    }
    @Override
    public void sale() {
        System.out.println("屋子出租价位有1k-3k"); // 增添新的操作
        target.sale(); // 挪用Entrust委托类的sale方式
    }
}

测试类

// 测试类,天生委托类实例工具,并将该工具传入署理类组织函数中。

public class Test {
    // 静态署理使用示例
    public static void consumer(Rental subject) {
        subject.sale();
    }
    public static void main(String[] args) {
        Rental test = new Entrust();
        System.out.println("---使用署理之前---");
        consumer(test);
        System.out.println("---使用署理之后---");
        consumer(new AgentRental(test));
    }
}

通过上面的例子,我们可以瞥见静态署理的优点:

我们可以在不改变Entrust委托类源代码的情形下 ,通过AgentRental署理类来修改Entrust委托类的功效,从而实现“署理”操作。在举行署理后,自界说说明屋子出租价位有1k-3k的操作方式。

但这个是我们通过署理类举行实现更改的方式,若是当我们需要过多的署理类对委托类举行修改的情形下,则可能泛起下图情形:

由此可以我们得知此静态署理的瑕玷:

当我们的接口类需要增添和删除方式的时刻,委托类和署理类都需要更改,不容易维护。

同时若是需要署理多个类的时刻,每个委托类都要编写一个署理类,会导致署理类繁多,欠好治理。

由于java静态署理是对类举行操作的,我们需要一个个署理类去实现对委托类的更改操作,针对这个情形,我们可以行使动态署理来解决,通历程序运行时自动天生署理类。

0x04 java动态署理简介

Java动态署理位于Java.lang.reflect包下,我们一样平常就仅涉及Java.lang.reflect.Proxy类与InvocationHandler接口,使用其配合反射,完成实现动态署理的操作。

InvocationHandler接口:卖力提供挪用署理操作。

是由署理工具挪用处置器实现的接口,界说了一个invoke()方式,每个署理工具都有一个关联的接口。当署理工具上挪用方式时,该方式会被自动转发到InvocationHandler.invoke()方式来举行挪用。

Proxy类:卖力动态构建署理类

提供四个静态方式来为一组接口动态天生的署理类并返回署理类的实例工具。

getProxyClass(ClassLoader,Class<?>...):获取指定类加载器和动态署理类工具。

newProxyInstance(ClassLoader,Class<?>[],InvocationHandler):指定类加载器,一组接口,挪用处置器;

,

Usdt第三方支付平台

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,

isProxyClass(Class<?>):判断获取的类是否为一个动态署理类;

getInvocationHandler(Object):获取指定署理类实例查找与它相关联的挪用处置器实例;

0x05 实现历程

1、使用java.lang.InvocationHandler接口建立自界说挪用处置器,由它来实现invoke方式,执行署理函数;

2、使用java.lang.reflect.Proxy类指定一个ClassLoader,一组interface接口和一个InvocationHandler;

3、通过反射机制获得动态署理类的组织方式,其唯一参数类型是挪用处置器接口类型;

4、挪用java.lang.reflect.Proxy.newProxyInstance()方式,划分传入类加载器,被署理接口,挪用处置器;建立动态署理实例工具。

5、通过署理工具挪用目的方式;

我们继续使用前面谁人例子举行解说,由于接口类和委托类不用更改,这里就不重复了。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TestAgent implements InvocationHandler {
    // target变量为委托类工具
    private Object target;
    public TestAgent(Object target) {
        this.target = target;
    }
    // 实现 java.lang.reflect.InvocationHandler.invoke()方式
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 添加自界说的委托逻辑
        System.out.println("屋子出租价位有1k-3k");
        // 挪用委托类的方式
        Object result = method.invoke(target,args);
        return result;
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class test {
    public static void main(String[] args) {
        // 获取委托类的实例工具
        Entrust testEntrust = new Entrust();
        // 获取CLassLoader
        ClassLoader classLoader = testEntrust .getClass().getClassLoader();
        // 获取所有接口
        Class[] interfaces = testEntrust .getClass().getInterfaces();
        // 获取一个挪用处置器
        InvocationHandler invocationHandler = new TestAgent(testEntrust);
        // 查看天生的署理类
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        // 建立署理工具
        Rental proxy = (Rental) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
        // 挪用署理工具的sayHello()方式
        proxy.sale();
    }
}

这里我们可以瞥见我们天生的动态署理类的字节码文件,放置在程序根目录下的com.sun.proxy.$Proxy0.class文件中。

import com.DynamicProxy.Rental;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Rental {
    // 私有静态组织方式
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;
    // 获取挪用处置器实例工具
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    // 获取挪用接口类的sale()方式,转发到挪用处置器中的invoke()方式举行处置。
    public final void sale() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    // 行使反射举行类初始化,执行static静态代码块中的内容,主要是获取com.DynamicProxy.Rental接口类中的sale方式。
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.DynamicProxy.Rental").getMethod("sale");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

在这里天生的$Proxy0代类中,我们可以清晰知道动态署理的实现历程。实际上我们在建立署理工具时,就是通过通过反射来获取这个类的组织方式,然厥后建立的署理实例。

0x06 ysoserial示例

在ysoerial工具中,实在基本许多poc或者exp都运用到了jdk署理机制。那么这个ysoerial工具是怎么实现jdk动态署理的呢?实在和ysoserial.payloads.util.Gadgets.createMemoitizedProxy()有关。

CommonsCollections1.java

final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);

RMIRegistryExploit.java

Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap(name, payload), Remote.class);

Spring2.java

final Object typeProviderProxy = Gadgets.createMemoitizedProxy(
            Gadgets.createMap("getType", typeTemplatesProxy),
            forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));

好比这上面这三处payloads和exploit都使用了createMemoitizedProxy来建立署理,跟进查看剖析。

public static <T> T createMemoitizedProxy ( final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces ) throws Exception {
       return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);
    }


    public static InvocationHandler createMemoizedInvocationHandler ( final Map<String, Object> map ) throws Exception {
       return (InvocationHandler) Reflections.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
    }


    public static <T> T createProxy ( final InvocationHandler ih, final Class<T> iface, final Class<?>... ifaces ) {
        final Class<?>[] allIfaces = (Class<?>[]) Array.newInstance(Class.class, ifaces.length + 1);
        allIfaces[ 0 ] = iface;
        if ( ifaces.length > 0 ) {
            System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length);
        }
        return iface.cast(Proxy.newProxyInstance(Gadgets.class.getClassLoader(), allIfaces, ih));
    }

我们可以对这三个函数举行简朴剖析下,挪用createMemoitizedProxy方式传入一个Map类型工具和多个接口类,然后返回createProxy方式来建立动态署理工具。

createMemoizedInvocationHandler方式传入一个Map类型工具和多个接口类,返回天生自界说挪用处置器,实现署理功效。

createProxy方式则是建立动态署理类,而且返回该署理工具实例。

我们将前面的动态署理机制学习和这三个函数举行毗邻在一起,可以得知就是通过createMemoitizedProxy方式传入一个Map类型工具和多个接口类,然后挪用createProxy方式中第一个参数createMemoizedInvocationHandler方式来自界说挪用处置器,最后返回createProxy方式建立动态署理类工具。

0x07 总结

由于java署理机制观点明白较于简朴,以是网上一些java平安解说很少关于这块内容举行单独文章解说。但这个知识点却是java破绽剖析中不能缺少,同时对后面RMI和JDNI注入学习也有很大辅助。若是人人对其有更多兴趣的话,还可以去看看其源码深入了解下。

0x08 参考链接

https://blog.csdn.net/huashanlunjian/article/details/84384279

https://www.guildhab.top/?p=6593

https://blog.csdn.net/JacksonKing/article/details/102974895

网友评论