def encrypt(m, a, si):
c=""
for i in range(len(m)):
c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
return c
if __name__ == "__main__":
m = '****************************************************flag{*************}'
assert(len(m)==71)
a = randint(50,100)
salt = ''.join(sample(ascii_uppercase, 4))
si = cycle(salt.lower())
c=encrypt(m, a, si)
print(c)
打开文件,从代码内容上来看,密文的形式是明文中每个字节的ascii值*a+未知ascii值%128
a是再50到100之间的数,可以爆破,salt是随机从A~Z之间的4个不重复的字母,可以爆破,关键在于怎么爆破?m的长度是71,测了一下确实是71,说明代码里m中的flag的位置和真正的明文中flag的位置是一样的,位于第53位,由于16进制一位会变成两位,那么对应到密文就是第105位
53和105是从1开始计数,由于代码下表从0开始计数,代码如下:
from itertools import *
from string import *
from random import *
from mitmproxy import sys
c="3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a"
m = '****************************************************flag{*************}'
#print(m.find('f'))
#52
salt = list(permutations(ascii_uppercase, 4))
for a in range(50,100):
print('try:',a)
for j in salt:
b=''
t=''
for k in j:
b+=k
b=b.lower()
for i in range(52,56):
t+=hex(((ord(m[i])) * a + ord(b[i-52])) % 128)[2:].zfill(2)
if t == c[104:112]:
print('a=',a)
print('si=',j)
sys.exit()
得到a=67,salt=“JESQ”
那么再用a和salt爆破一下m
from string import *
from itertools import *
a=67
salt = 'jesq'
s = cycle(salt)
c = '3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a'
flag=''
for i in range(len(c)//2):
b=c[:2]
c=c[2:]
s1=next(s)
for k in range(32,127):
c1=hex((k* a + ord(s1)) % 128)[2:].zfill(2)
if c1==b:
flag+=chr(k)
break
print(flag)
#now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}
now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}
意思是,now is 7fad9fcb-d361-4964-821c-177c906b8d20
flag是经过md5加密的now-salt,salt是JESQ,那么now-salt就是
7fad9fcb-d361-4964-821c-177c906b8d20-JESQ,
扔到md5里加密一下,得到 1efce62ee0a96e39149e2179db1dd04c