Hed9eh0g

前进的路上总是孤独的

记一道Xor密码题

本文共计有2811个字

前言

xor运算与相关规律我在之前的一篇文中已经有所记录,但是对于单纯把xor运算用于加密的题目我还没练过,结合18年强网杯的一道相关的题在此做一下记录。

题目引入

18年强网杯 FEZ
首先得到一个用于加密脚本fez.py:

import os
def xor(a,b):
    assert len(a)==len(b)
    c=""
    for i in range(len(a)):
        c+=chr(ord(a[i])^ord(b[i]))
    return c
def f(x,k):
    return xor(xor(x,k),7)
def round(M,K):
    L=M[0:27]
    R=M[27:54]
    new_l=R
    new_r=xor(xor(R,L),K)
    return new_l+new_r
def fez(m,K):
    for i in K:
        m=round(m,i)
    return m
 
 K=[]
 for i in range(7):
 K.append(os.urandom(27))
 m=open("flag","rb").read()
 assert len(m)<54
 m+=os.urandom(54-len(m))test=os.urandom(54)
 print test.encode("hex")
 print fez(test,K).encode("hex")
 print fez(m,K).encode("hex")

除了这个脚本外还给了另外三串数据:

2315d80c2dd73098953686be6c82aa63c1d362eb0095e4621cce28bec4c921ce016afc7f39fd93b14b6c28ce69c7096b91fd2db0862d

308e590a180473ab4d23a0c67b65fe2bf2d0a9f1b255e4e2610b0c90e8e210c8ed4f2b9a3b09c1886a781f94fee4f77488c0b30f2395

e822e918e578a7af4f0859a99aab5d7563644beb4207a73d5fc4560d3deb696320cec479431a4f724310499baf5230db7e56764915d0

根据脚本我们可以知道,这三串数据分别就是脚本最后部分的三个print输出。也就是说我们已知三个加密结果,再来看看脚本具体是在干什么:

存在的变量

1、K是一个随机生成的列表,内有7个元素,每个元素是27个字符。
2、生成一个随机的含54位的test变量,而且三个输出中第一个输出就是变量test的hex编码(也即test已知),第二个输出是通过test与K加密得到的hex编码(也即加密test之后的值已知)。
3、m变量是54位变量,而且m的前面一部分包含着flag,剩余不足54位的部分就是随机值。三个输出中的第三个输出是通过m与K加密得到的hex编码(也即加密m之后的值已知),既然m包含flag那么m就是我们想求的变量,目前我们只能知道加密m之后的值。
因此现在应该了解加密算法,才能根据加密结果来反推出明文m:

加密算法

对于加密算法,加密函数最外层是fez,然后fez中循环调用round函数进行加密,每一次循环都是使用K中的一个随机字符串,其中round是真正实现加密的过程,是一个异或的过程:
先将54位的参数M分为左右两部分,再根据这两部分生成新的左右两部分,其中新的左部分为原来的右部分,新的右部分是原来左右两部分异或之后再与另外一个27位参数K进行异或(参数K就是7层列表K中的一层,之前i的7次循环,假设每一层分别为:K1、K2、K3、…..、K6、K7)。可以列出加密过程:
1、对test的加密(应用异或规律进行运算,其中把test分为左右部分L、R):

初始层 L R
第一层 R L^R^K1
第二层 L^R^K1 L^K1^K2
第三层 L^K1^K2 R^K2^K3
第四层 R^K2^K3 L^R^K1^K3^K4
第五层 L^R^K1^K3^K4 L^K1^K2^K4^K5
第六层 L^K1^K2^K4^K5 R^K2^K3^K5^K6
第七层 R^K2^K3^K5^K6 L^R^K1^K3^K4^K6^K7

而第七层的R^k2^k3^k5^k6 + L^R^k1^k3^k4^k6^k7再进行hex编码之后其实就是第二个输出。
假设:L’=R^k2^k3^k5^k6,R’=L^R^k1^k3^k4^k6^k7
2、对m的加密(同样应用异或规律进行运算,假设m也与可分为左右部分m1、m2):
同理可得m2^k2^k3^k5^k6 + m1^m2^k1^k3^k4^k6^k7再进行hex编码之后其实就是第三个输出。
假设:m1’=m2^k2^k3^k5^k6,m2’=m1^m2^k1^k3^k4^k6^k7

求出m得到flag

根据异或规律可以推导出:m=m1+m2=(m2’^m2^k1^k3^k4^k6^k7)+(m1’^k2^k3^k5^k6)=(m2’^m2^R’^L^R)+(m1’^L’^R)=(m2’^m1’^k2^k3^k5^k6^R’^L^R)+(m1’^L’^R)=(m2’^R’^m1’^L^L’ )+( m1’^L’^R)
也即:m=(m2’^R’^m1’^L^L’ )+( m1’^L’^R),由于L、R、L’、R’、m1’、m2’都已知,因此最终可以求出m,求解的脚本如下:

def xor(a,b):
    assert len(a)==len(b)
    c=""
    for i in range(len(a)):
        c+=chr(ord(a[i])^ord(b[i]))
    return c
 test = '2315d80c2dd73098953686be6c82aa63c1d362eb0095e4621cce28bec4c921ce016afc7f39fd93b14b6c28ce69c7096b91fd2db0862d'.decode("hex")
 fez1 = '308e590a180473ab4d23a0c67b65fe2bf2d0a9f1b255e4e2610b0c90e8e210c8ed4f2b9a3b09c1886a781f94fee4f77488c0b30f2395'.decode("hex")
 fez2 = 'e822e918e578a7af4f0859a99aab5d7563644beb4207a73d5fc4560d3deb696320cec479431a4f724310499baf5230db7e56764915d0'.decode("hex")

 L = test[0:27]
 R = test[27:54]
 L'= fez1[0:27]
 R' = fez1[27:54]
 m1' = fez2[0:27]
 m2' = fez2[27:54]
 m = xor(xor(xor(xor(m2', R'), m1'), L), L') + xor(xor(m1', L'), R)
 print m

最终即可得到flag

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注