下载题目附件后,给出了一份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,"\n") 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\做题文件\CsiCtf\Esrever\esrever.txt","rb") b=fp.readlines() #下面是读出来的encrypted text entext = b"\xc2\xbb\xc2\xb7\xc2\xad\xc2\xaa\xc2\xbb\xc2\xa3\xc2\xb5\xc2\xb1\xc2\xac\xc2\xa5\xc2\xbc\xc2\xb1\xc2\xba\xc2\xb5\xc2\xb1\xc2\xbf\xc2\xb7\xc2\xa3\xc2\xa6\xc2\xad\xc2\xb4\xc2\xaf\xc2\xaa\xc2\xa8\xc2\xa5\xc2\xab\xc2\xa5\xc2\xa6\xc2\xab\xc2\xb4\xc2\xb8\xc2\xa6\xc2\xa1\xc2\xb8\xc2\xa2\xc2\xb2\xc2\xa7\xc2\xa4\xc2\xa6\xc2\xa6\xc2\xb9\xc2\xa8" 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啦!!!