导语

点击这里去答题

打开可以看到一个.pyo的文件和一个.enc的文件

其中.pyo是python编译后的字节码文件,可以使用EasyPythonDecomplier进行反编译,获取对应的python代码。同时也有在线工具可以用。
而.enc应该是经过了encrypt加密后的结果,内容是

208 140 149 236 189 77 193 104 202 184 97 236 148 202 244 199 77 122 113 

将.pyo反编译,可以得到这样的代码:

# Embedded file name: encrypt.py
from random import randint
from math import floor, sqrt
_ = ''
__ = '_'
____ = [ ord(___) for ___ in __ ]
_____ = randint(65, max(____)) * 255
for ___ in range(len(__)):
_ += str(int(floor(float(_____ + ____[___]) / 2 + sqrt(_____ * ____[___])) % 255)) + ' '

print _

一样长的下划线代表一个变量,可以稍微优化一下

from random import randint
from math import floor, sqrt
emcrypted = ''
plain = '_'
plain_ascii = [ ord(i) for i in plain ]
randI = randint(65, max(plain_ascii)) * 255
for i in range(len(plain)):
emcrypted += str(int(floor(float(randI + plain_ascii[i]) / 2 + sqrt(randI * plain_ascii[i])) % 255)) + ' '

print emcrypted

可以看出来,加密步骤如下
首先将明文转为对应的ascii码表示
然后再从65~max(plain_ascii)中随机选取一个整数再乘以255得到randI
然后对每个明文的ascii码i进行如下操作
1 加上randI,除以二
2 乘以randI,开平方,再模255
3 把1和2两步的结果加起来,强转整型

由于第三步强转整型是会有数据丢失的,所以没法直接逆算法求明文,但是他只rand了一次,并且rand的取值也没多少,所以直接暴破即可

from random import randint
from math import floor, sqrt


ANSInum = [i for i in range(33,127)]
flagEnc=[208,140,149,236,189,77,193,104,202,184,97,236,148,202,244,199,77,122,113]

for k in range(65*255,127*255,255):
tmpDict={} #解码表
for i in range(len(ANSInum)):
tmpInt = int(floor(float(k + ANSInum[i]) / 2 + sqrt(k * ANSInum[i])) % 255)
tmpDict[tmpInt] = chr(ANSInum[i])
try:
flag=''.join([tmpDict[i] for i in flagEnc])
print ('flag{' + flag + '}')
print (k/255)
except:
pass


甚至只有一个结果=-=