[Crypto]God Says xp0int Posted on Oct 28 2018 # God Says <br> 题意很好理解,给你12段密文,告诉你都是由一个密钥异或得来的,想必其中一段明文中就藏着密文。urandom本身是当作随机字节流来用的,所以我们把它当成无限密钥流就好了。 <br> 下面有必要讲一下异或的特性: key⊕m=c 欲求m只需要key⊕c=m,让c再异或一遍key,那么现在主要的问题就是利用这12段密文来推测出密钥是多少了。 个人使用的推测手法如下(以第一位密钥为例): <br> ```python for k in range(0,1): key_guess = [] key_test=[] for i in range(0x00,0x100): key_guess.append(i) key_test.append(i) for i in key_test: for j in c[k]: if chr(i^j) not in required_string: key_guess.remove(i) break print(key_guess) for i in key_guess: for j in c[k]: print(chr(i^j),end='') print('') ``` <br> 原理如上代码,密钥的选取范围为0x00~0xFF,第一列的密文都是由同一位密钥产生的产生的,这时候我们要做一个假设,来对产生的可能密钥做一下减枝,即每段密文的首字母都是大写字母,设required_string = string.ascii_uppercase,结果会发现可能的密钥集合输出为空,说明假设的范围太小了,不妨扩大一点加多一个空格,输出的猜测结果就如下图(最后两个为空格): ![](https://leanote.com/api/file/getImage?fileId=5bd45913ab64411fb800520a) <br> 然后猜测后文应该会出现小写字母,则再次变更条件required_string = string.ascii_uppercase+' '+string.ascii_lowercase,再利用上述代码猜测第二、三列,结果如下: ![](https://leanote.com/api/file/getImage?fileId=5bd45913ab64411fb800520c) <br> 发现第三列的猜测范围出错了,说明需要补充密文的猜测范围,这时候可以结合已经猜出来的前两文去推测,前两位结果如下**(用“_”代替空格)**: ```python Le An If Re Be Po A We Th Pe __ __ ``` <br> 根据词法猜测,第三段的一个单词应该是If(如果)则第三个字符应该为空格,我们对照原文找一下,第三段的第三个字符的ascii码应该为162,而162^ord(" ") =130,所以我们猜测第三位密钥为130,则对应第三列的密文解密出来应该是: ```python Let Any If_ Rel Bet Pol A_s We_ The Peo __- __Y ``` <br> 在猜出了原文的情况下同时也可以利用出现的新字符(例如本例中的“-”)来补全密文的猜测范围。required_string = string.ascii_uppercase+' '+string.ascii_lowercase+'-',当然你也可以提前补充预设可能会出现哪些字符,比如“{”、“}”、“'”之类的,遇到多个可能的都输出来然后拼接到已猜测出来的原文中,看哪个更符合语法和词法。当然了我们也没必要全部明文都靠猜出来,当我们解出一定数量的明文后我们可以去搜索引擎上进行关键字搜索,看是否有相关的原文,直接拿来与密文异或推导出密钥,最终将所有密文解出。 例如在猜到如下程度: ``` Let_us_not_look_back_in_anger Any_sufficiently_advanced_bug If_privacy_is_outlawed,_only_ Relying_on_the_government_to_ Better_be_despised_for_too_an Politically_Correct_Virus:_Do A_secure_system_is_one_that_d We_will_bankrupt_ourselves_in The_user's_going_to_pick_danc People_don't_react_to_reality __---- __You_deserve_it: flag{In_God ``` <br> 很明显了,flag在最后一行中因此,按照上述过程随便选一组原文关键字去搜索,然后解出密钥,最终解出密文得到flag,我选用的是“We will bankrupt ourselves in the vain search for absolute security”,代码如下: ```python m='We will bankrupt ourselves in the vain search for absolute security' m_test=[] for i in m: m_test.append(ord(i)) m_test=m_test[0:65] m='130ea2c7d02af0651f718668753d2d21181c1f0ce25a1821bb53e44c0019200073ba51430170514a47c2ea1f76ac29008f5e6bbafccb210ef38ea7178af5e7d9bf' tmp =[] for j in range(0,130,2): tmp.append(int(m[j:j+2],16)) key=[] for i in range(0,65): key.append(tmp[i]^m_test[i]) m='644bdbdfcc66f8200e759a756268342102530c12f0580f1eb000834a0a19230d36ee55571b6a5f1963cff45c71f8270a8f0d2aafea843b12f59ef4449cf5f3c5ab' c=[] for j in range(0,130,2): c.append(int(m[j:j+2],16)) ans = '' for i in range(0,65): ans=ans+chr(c[i]^key[i]) print(ans) ``` <br> 运行即可输出最后一行flag. ![图片标题](https://leanote.com/api/file/getImage?fileId=5bd45913ab64411fb800520b) 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [Misc]bitcoin_base [Misc]加密了吗
没有帐号? 立即注册