今天在熊猫 TV 上看乌云白帽子大会,下面有三道互动的题目挺有意思的。
前面两题都很简单,第一题是解一个莫斯电码、第二题答案很简单,但是要提交答案需要在网页源码上懂点手脚。
第三题是重头戏,不过难度也不高,题目如下:
第三题每个人的答案都不一样,图片里被我划掉的这部分是我的用户名(手机号) K。
红色部分的一串数字就是经过上面的 DEKHash 算出的结果,所以题意就很明显了,找到 K'
使得 DEKHash(K') == DEKHash(K)
。
题目中给出的是 Java 代码,我作为 Java 黑,显然是不能忍受的,所以弄成了 C++的版本:
|
|
下面来看我是怎么寻找这样的 K'
。
思路
本科的时候对安全相关的技术很有兴趣,但是由于各种忙从来没接触过,今天刚好又是周六看起了直播,所以也算是第一次尝试。
首先,这个 DEKHash 的计算方法显然是跟字符串的长度有关的,所以我们寻找的碰撞 K'
的长度应该和我们原来的 K
的长度相同。
验证纯数字
因为用户名是手机号码,所以一开始我会想要穷举11位的所有手机号是否有重复的 Hash:
|
|
不过跑了一段一小会儿就放弃了,但是从观察到的输出来看,发现了一个规律:
|
|
在这个结果下,只有末尾号码发生变化,最后算出来的值只有最后两位才会发生变化。
所以很明显,如果只是纯数字的号码,找到Hash 值相同的 K'
只能够在最后一位不同的情况下寻找,一共才十个号码,很容易验证没有这样的 K'
。
所以纯数字的结果马上就可以放弃了。
随机搜索
最开始的时候我们已经分析过K'
的串场要与K
相同,既然纯数字不可能,那么只能从字符串中搜索了。
下面这个函数是一个生成长度为 len
的随机字符串,字符串会包含数字、大小写字母。
|
|
这样的话,我们重新编写搜索函数:
|
|
这样的话,跑一跑马上就能找到了:
|
|
你可能会问,string first = "3x63qqR"
这段是怎么来的?
首先这段字符串并不知道,是一步步迭代来的。
string first
首先应该设置为 ""
,而 search_length
的值设置为 12
(留一个单元保存 \0
),然后开始跑结果,当然不太可能马上就能获得结果,但是我们至少能够获得一部分结果,然后在输出的结果中用我们已知的 hash 值的一部分在 value 中搜索以 379207836497504850
前面几位开头的值,查找有没有匹配的结果,如果有,反复人肉,就能够一步步得到所需的串头了。
自动碰撞程序
人肉方案做出来显然有点低效率,我们不如编写一个自动化搜索的函数,这稍微需要一点精力,思路是,可以先随机跑出来一定大小的样本,然后在样本中进行搜索,确定一小部分串头,如此反复。
但是从另一方面看,其实我是第一个解出这道题的人,用的就是人肉的方法,如果还要花精力编写一个自动碰撞的程序,可能就不会是第一个解出的人了。
所以,既然思路已经有了,这个程序就留给有意者写吧。