# afctf 一道有趣的题目

链接

#加密代码
def encrypt(plainText):
    space = 10
    cipherText = ""
    for i in range(len(plainText)):
        if i + space < len(plainText) - 1:
            cipherText += chr(ord(plainText[i]) ^ ord(plainText[i + space]))
        else:
            cipherText += chr(ord(plainText[i]) ^ ord(plainText[space]))
        if ord(plainText[i]) % 2 == 0:
            space += 1
        else:
            space -= 1
    return cipherText
    
# 密码
# 15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206

首先可以知道明文的长度

这里有一个坑,他给的是 hex,要转成字节,28 位

要知道每一位的奇偶性,才能知道 space 的变化

28 位可以爆破

def get_temp(cipher):
    for x in range(1 << len(cipher)):
        temp = bin(x)[2:].zfill(len(cipher))
        space = 10
        flag = 0
        for i in range(len(temp)):
            if i + space < len(temp) - 1:
                tempx = int(temp[i]) ^ int(temp[i + space])
            else:
                tempx = int(temp[i]) ^ int(temp[space])
            if tempx != (cipher[i] % 2):
                flag = 1
                break
            elif int(temp[i]) % 2 == 0:
                space += 1
            else:
                space -= 1
        if flag != 1:
            return temp
            break

得到末位的奇偶性
然后得到每一位和另一位的异或

space=10
c=[]
for i in range(len(cipher)):
    if i + space < 28 - 1:
        a=[i,i+space]
    else:
        a=[i,space]
    if ord(tmp[i]) % 2 == 0:
        space += 1
    else:
        space -= 1
    c.append(a)
print(c)

因为这道题目的 flag 是以 'afctf {' 开头的,就可以继续爆破了

plain=['a','f','c','t','f','{']+[-1]*22
while -1 in plain:
    for i in range(26):
        if(plain[i]!=-1):
            plain[c[i][1]]=chr(cipher[i]^ord(plain[i]))
        elif(plain[c[i][1]]!=-1):
            plain[i]=chr(cipher[i]^ord(plain[c[i][1]]))
for i in plain:
    print(i,end='')