csictf-Esrever

下载题目附件后,给出了一份python的脚本esrever.py和一份放有Encrypted Key和Encrypted Text的文档,直接猜测是根据加密算法写出解密脚本得出flag.

esrever.py如下:

import random

# TODO: Remember to remove real flag before deploying
flag = 'csictf{fake_flag}'

key = 'fake_key'

def enc1(text):
    r = random.randint(1,25)
    return bytes.fromhex(''.join([hex(((ord(i) - ord('a') - r) % 26) + ord('a'))[2:] for i in text])).decode('ascii')

def enc2(text, key):
    k = [key[i % len(key)] for i in range(len(text))]
    return ''.join([chr(ord(text[i]) ^ ord(k[i]) + ord('a')) for i in range(len(text))])

def enc3(text):
    mapping = [28, 33, 6, 17, 7, 41, 27, 29, 31, 30, 39, 21, 34, 15, 3, 5, 13, 10, 19, 38, 40, 14, 26, 25, 32, 0, 36, 8, 18, 4, 1, 11, 24, 2, 37, 20, 23, 35, 22, 12, 16, 9]

    temp = [None]*len(text)
    for i in range(len(text)):
        temp[mapping[i]] = text[i]
    
    return ''.join(temp)

def enc4(text):
    mapping = [23, 9, 5, 6, 22, 28, 25, 30, 15, 8, 16, 19, 24, 11, 10, 7, 2, 14, 18, 1, 29, 21, 12, 4, 20, 0, 26, 13, 17, 3, 27]

    temp = [None]*len(text)
    for i in range(len(text)):
        temp[i] = text[mapping[i]]
    
    return ''.join(temp)

encryptedText = enc1(flag)
encryptedKey = enc1(key)
for i in range(random.randint(1,100)):
    encryptedText = enc1(encryptedText)
    encryptedKey = enc1(key)

print('Encrypted Key = ' + enc4(enc4(encryptedKey)))
print('Encrypted Text = ' + enc3(enc3(enc2(enc1(encryptedText), key))))

给出的文档如下:

Encrypted Key = ieluvnvfgvfahuxhvfphbppnbgrfcrn
Encrypted Text = »·­ª»£µ±¬¥¼±ºµ±¿·£¦­´¯ª¨¥«¥¦«´¸¦¡¸¢²§¤¦¦¹¨

首先观察算法,发现除了enc1函数,其他函数都不涉及到随机数的问题,且虽然enc1涉及到了随机数,但可能性只有26种,一开始感觉可以通过爆破得出,但后来发现最后封装还有个for i in range(random.randint(1,100)):,于是打消了念头,先把函数enc2、enc3、enc4、的逆函数写了出来。后来仔细观察enc1,发现函数enc1实际上是一个随机凯撒加密,这么一想,答案也就出来了,不论一个字符串通过enc1加密多少次,也只会有26种结果!!!于是可以先把key求出来(一共有26种可能),在分别求出每种可能对应的text,再把对应的text进行26次凯撒解密,找出字符串中有关键字'csictf'也就是flag!

脚本如下:

def reenc4(text):
    mapping = [23, 9, 5, 6, 22, 28, 25, 30, 15, 8, 16, 19, 24, 11, 10, 7, 2, 14, 18, 1, 29, 21, 12, 4, 20, 0, 26, 13, 17, 3, 27]
    temp = [None]*len(text)
    for i in range(len(text)):
        temp[mapping[i]] = text[i]
    return ''.join(temp)

enkey='ieluvnvfgvfahuxhvfphbppnbgrfcrn'
enkey=reenc4(enkey)
enkey=reenc4(enkey)
print(enkey,"
")



table='abcdefghijklmnopqrstuvwxyz'
enc1table=[]
"""
def reenc1(text):#还没意识到是凯撒加密时写的reenc1
    for r in range(1,26):
        n=''
        for char in text:
            for i in range(26):
                x=(ord(table[i])-ord('a')-r)%26+ord('a')
                if(x==ord(char)):
                    n+=table[i]

        print(n)
        enc1table.append(n)
    return enc1table
"""

def reenc1(text):
    for r in range(1,26):
        n=''
        for char in text:
            x=chr((ord(char)-ord('a')-r)%26+ord('a'))
            n+=x
        enc1table.append(n)
    return enc1table


def reenc2(entext,key):#这里要注意运算符优先级!!!
    k = [key[i % len(key)] for i in range(len(entext))]
    detext=''
    for i in range(len(entext)):
        x=chr((ord(entext[i])^(ord('a')+ord(k[i]))))
        detext+=x
    return detext

def reenc3(text):
    mapping = [28, 33, 6, 17, 7, 41, 27, 29, 31, 30, 39, 21, 34, 15, 3, 5, 13, 10, 19, 38, 40, 14, 26, 25, 32, 0, 36, 8, 18, 4, 1, 11, 24, 2, 37, 20, 23, 35, 22, 12, 16, 9]
    temp = [None]*len(text)
    for i in range(len(text)):
        temp[i] = text[mapping[i]]
    
    return ''.join(temp)


fp=open("D:Desktop做题文件CsiCtfEsreveresrever.txt","rb")
b=fp.readlines()
#下面是读出来的encrypted text
entext = b"xc2xbbxc2xb7xc2xadxc2xaaxc2xbbxc2xa3xc2xb5xc2xb1xc2xacxc2xa5xc2xbcxc2xb1xc2xbaxc2xb5xc2xb1xc2xbfxc2xb7xc2xa3xc2xa6xc2xadxc2xb4xc2xafxc2xaaxc2xa8xc2xa5xc2xabxc2xa5xc2xa6xc2xabxc2xb4xc2xb8xc2xa6xc2xa1xc2xb8xc2xa2xc2xb2xc2xa7xc2xa4xc2xa6xc2xa6xc2xb9xc2xa8"
entext=(entext.decode())
entext=reenc3(reenc3(entext))


keytable=reenc1(enkey)
#print(keytable)
texttable=[]for strkey in keytable:
    x=reenc2(entext,strkey)
    #print(enc2(x,strkey))
    texttable.append(x)
#print(texttable)

for textstr in texttable:
    x=reenc1(textstr)
    for i in x:
        if "csictf" in i:
            print(i)

运行后结果如下:

 得出字符串'csictfaesreverisjustreverseinreverserightc'就是我们的flag,但我们需要把a改为'{',把最后的c改为'}',因为管理员有说格式不变,而改了之后的字符串也就是我们的flag啦!!!

原文地址:https://www.cnblogs.com/jane315/p/13386317.html