Tags: crypto vigener

Rating: 5.0

Clam managed to get parole for his dumb cryptography jokes, but after making yet another dumb joke on his way out of the courtroom, he was sent straight back in. This time, he was sentenced to 5 years of making dumb Vigenere challenges. Clam, fed up with the monotony of challenge writing, made a program to do it for him. Can you solve enough challenges to get the flag?

Connect to the challenge at nc challs.actf.co 31333. Source(main.py)

Source(main.py)


#!/usr/local/bin/python3

import string
import os
import random

with open("flag.txt", "r") as f:

alpha = string.ascii_lowercase

def encrypt(msg, key):
ret = ""
i = 0
for c in msg:
if c in alpha:
ret += alpha[(alpha.index(key[i]) + alpha.index(c)) % len(alpha)]
i = (i + 1) % len(key)
else:
ret += c
return ret

inner = alpha + "_"
noise = inner + "{}"

print("Welcome to the vinegar factory! Solve some crypto, it'll be fun I swear!")

i = 0
while True:
if i % 50 == 49:
fleg = flag
else:
fleg = "actf{" + "".join(random.choices(inner, k=random.randint(10, 50))) + "}"
start = "".join(random.choices(noise, k=random.randint(0, 2000)))
end = "".join(random.choices(noise, k=random.randint(0, 2000)))
key = "".join(random.choices(alpha, k=4))
print(f"Challenge {i}: {start}{encrypt(fleg + 'fleg', key)}{end}")
x = input("> ")
if x != fleg:
print("Nope! Better luck next time!")
break
i += 1



My script


#!/usr/bin/env python3
from pwn import *
import string

s = remote("challs.actf.co", 31333)
#s = remote("127.0.0.1", 31333)

for t in range(52):
s.recvuntil('Challenge')
noise = str(s.recvuntil('\n'))
print(noise)
s.recvuntil('> ')
alphabet = string.ascii_lowercase
length = int(len(noise))

output_file = open('output.txt', 'w')
for i in range(0, length-35):
if noise[i] in alphabet and noise[i + 1] in alphabet and noise[i + 2] in alphabet and noise[i + 3] in alphabet:
if noise[i + 4] == '{':
a = noise[i:i + 6]
i=i+3
while noise[i + 2] != '}' and noise[i + 2] != '{' and noise[i+2] != '\n':
i = i + 1
a = a + (noise[i + 2])
if noise[i+2] == '{':
continue
if noise[i + 3] in alphabet and noise[i + 4] in alphabet and noise[i + 5] in alphabet and noise[i + 6] in alphabet:
a = a + (noise[i + 3:i + 7])
# arr.append("a")
output_file.write(a + '\n')
#
# print(a)
# print('\n')
else:
continue
output_file.close()

with open('output.txt') as fp:
while line:
noiseflag = line.strip()
enc = line
dec = 'actf'
k = ''
alphabet = string.ascii_lowercase
for i in range(0,4):
need_index = (alphabet.index(enc[i]) - alphabet.index(dec[i]) + 26) % 26
k = k + alphabet[need_index]
msg = ''

def decrypt(ciph, key):
ret = ''
i = 0
for m in ciph:
if m in alphabet:
ret=ret+alphabet[(alphabet.index(m)- alphabet.index(key[i])) % len(alphabet)]
i = (i+1) % 4
else:
ret = ret + m
return ret
if decrypt(noiseflag, k)[-4:]=='fleg':
dec_input = decrypt(noiseflag, k)
print(dec_input.encode()[:-4])
s.sendline(dec_input.encode()[:-4])


This script does not work every time, the problem is that I don't know how to use python3 properly.
And the problem is that at the end of the noise it finds a suitable duration of 4 literal characters and the { character, and it starts reading empty characters outside the string, and the python swears at this.
How I fixed it (not very correct), I just run the loop to the length of the string - 35.

And the principle of the algorithm is simple
1) Reads a line starting with "Challenge", then finds a suitable sequence format. For example dghr{fbhnem}fbhd
2) Writes all matching sequences to output.txt
3) Reads the file output.txt line by line
4) finds a key so that at the beginning the first letters would be decoded as "actf", and if there is a string where the last 4 letters are expanded as "fleg", the script sends this string
5) And so 50 times

Try to fix my mistake and good luck!