Hi everyone! C:
This is a crypto challenge that I enjoyed a lot and I wanted to make my first blog post on my blog with this writeup, so finally now I have it :D
So basically we have…
This is the flag encrypted:
11d.3ilVk_d3CpIO_4nlS.ncnz3e_0S}M_kn5scpm345n3nSe_u_S{iy__4EYLP_aAAall
and this is the code that encrypted that:
import random
from flag import flag
def encrypt(msg, perm):
W = len(perm)
while len(msg) % (2*W):
msg += "."
msg = msg[1:] + msg[:1]
msg = msg[0::2] + msg[1::2]
msg = msg[1:] + msg[:1]
res = ""
for j in xrange(0, len(msg), W):
for k in xrange(W):
res += msg[j:j+W][perm[k]]
msg = res
return msg
def encord(msg, perm, l):
for _ in xrange(l):
msg = encrypt(msg, perm)
return msg
W, l = 7, random.randint(0, 1337)
perm = range(W)
random.shuffle(perm)
enc = encord(flag, perm, l)
f = open('flag.enc', 'w')
f.write(enc)
f.close()
We need to reverse this code and create a decrypt function.
Reversing…
- So, first let’s look at the starting lines: we have a random list from 0 to 6 and a random number from 0 to 1337;
- The
encord
function callencrypt
function L(random number(0,1337)) times; - In the
encrypt
function, the firstwhile
will just add 2 points on encrypted flag; - The
msg[1:] + msg[:1]
will put the first char at the end; - The
msg[0::2] + msg[1::2]
will split themsg
and zip; - The
msg[1:] + msg[:1]
will put the first char back at the end again; - The last double
for
will shuffle themsg
with the random list logic.
Solution…
The weakness of this crypto is that the key(The random list) has 5040 possibilities, so we just need to brute it C:
We can do it with itertools.permutations
The Jurandir Solver
import itertools
def str_perm(flag, p):
res = ""
for j in xrange(0, 70, 7):
for k in xrange(7):
res += flag[j:j+7][p.index(k)]
return res
def shuf(flag):
flag = flag[-1:] + flag[:-1]
new = ""
for i, j in zip(flag[:len(flag)//2], flag[len(flag)//2:]):
new += i+j
flag = new
flag = flag[-1:] + flag[:-1]
return flag
def main():
perm = list(itertools.permutations([0,1,2,3,4,5,6]))
first_flag = open("flag.enc", "r").readlines()[0]
for idx, p in enumerate(perm):
flag = first_flag
print str(idx)+"/5040"
for _ in xrange(1337):
res = str_perm(flag, p)
res = shuf(res)
if res.startswith("ASIS{"):
print res
exit(1)
flag = res
if __name__ == "__main__":
main()
Running the solver, after 805 iterations, we have the flag: ASIS{1n54n3ly_Simpl3_And_d3lic1Ous_5n4ckS_eVEn_l4zY_Pe0pL3_Can_Mak3}