Tags: brute-force python 


### TokyoWesterns CTF 4th 2018. *SCS7* Writeup by E-Toolz team

`https://score.ctf.westerns.tokyo/problems?locale=en` - Link

Firstly we connect to the server via netcat:
`nc crypto.chal.ctf.westerns.tokyo 14791`


We see that:
encrypted flag: r9QXENhJdbSiyxWWp2qPcWNyeL8tFVphhnZxXCyf0MAzAReVm69P6QGz0kfpA6DW
You can encrypt up to 100 messages.

Pushing some random buttons:
message: a
ciphertext: do
message: aa
ciphertext: TuN
message: aaa
ciphertext: Nxyu
message: b
ciphertext: d4
message: ab
ciphertext: TuE
message: aab
ciphertext: NxyS
message: aac
ciphertext: NxyJ


The main idea is to send the particular message to get a encrypted flag.
That message is our flag to submit

Experimentally we understood that
1. the cyphertext mostly depends on the message lenght and the last character.
2. The lenght must be exactly 47 symbols and since the flag format is TWCTF{<...>} that means that there is **only** a 40 characters to get

We had a hard time thinking about the principles of encoding, so we decided to just **brute force it :>**


> Brute force is not the best way because it takes much more time to check all options then trying to analyze but
> **who cares?** Please check other writeup's to understand the proper way.

So we wrote a python-scrypt to get through the char-list:

from pwn import *
from Levenshtein import distance
import string

for char in list("a"): #change len(list) to try more symbols
#connecting to the server, getting the enc_flag
r = remote("crypto.chal.ctf.westerns.tokyo",14791)
mask = 'TWCTF{67ced5346146c105075443add26fd7efd72763dd}' # change for your needs
# mask +=char # uncomment to apply more symbols in list
enc_flag = str(r.recvline()[16:80])
print enc_flag + "\n\r" + " with mask",mask+"\n" #get enc_flag
r.recvuntil('\n',drop=True) # just skipping the line

#setting up the charset lower-case + numbers
chars = list("abcdefg") + list(range(0,10)) # list(string.ascii_uppercase)

#here we generate const string
#coz last symbols doesn't really matter
def gen_temp_const(fchar):
#fchar = 0 by default
global tmp_const
for i in range(0,39-fchar):

#sending msg with a specified string
def msg_send(mask,const,foreach):
# print mask+const+"}\n" + "DEBUG"
enc_msg = r.recvline()[21:85]
#print enc_msg,curret character and Levenshtein distance
print enc_msg,chars[foreach],distance(enc_flag,enc_msg) #compare strings with Lev distance enc_msg,

#creating the - "const[0]" - first char from charset
def gen_const(foreach,tmp_const): # consts generated
global const
const = ''

def main():
gen_temp_const(len(mask)-6) #cheking "known" symbols with cut
for i in range(0,len(chars)):


At the output we'v got something like that:
with mask TWCTF{

yzvEZ2879EQJZmAgjt84119zNb446ySULqEgdMaRAjJVwMfqhjGmPVJPN1xGz2bt a 56
yzvEZ2879qzv4Lij7gsgA1oLvJDbfmfzNgjrxqCMqJ4U66LV94wFeqGAyA9PzXBr b 52
yzvEZ2879hJPxdBEm1pfZenxoBS5H05rFLqMUb1y2aabWWdyrfnjiSjHF2LXovdi c 55
yzvEZ2879ZegeUGAJ2s4zUuVdujZZbFG9ju8w1BL4vHjmmRBgqYaSpmVwxGWojFd d 55
yzvEZ2879bs2MEkPtMpgBRFXhdP8xS68sVSoEPqhxnvRdiVkRCbn7D6L9MoRoc4n e 51
yzvEZ2879rv4A52FGiffhReENK9h9NjgKE8ASa5cU7zdVLnsnkBt1nhqmuYcoz75 f 54
yzvEZ2879xM0qJRYaHp4QsCQkBUugvJA0H2G56xCMtbj1R11NudK4iFWRiuF3MiD g 55
yzvEZ287fMFVnizYjMomREV1fE2eGCVzpFVeen5vwHYqzHVsSEDtGyRcp5oZnbtT 0 53
yzvEZ287f7yhQfVMFigCEV9uxZuJ3p3rTBgLMJxFN01vaKG1kbkKgEiGhJYYnKHW 1 54
yzvEZ287fHHGKjtkmHoq5VzJGXEoBjhGLYWCH7mEuuCrwD1ziR5kMgubT7WrbFQg 2 53
yzvEZ287fgjQvbyf3oqmJjnWTvFxTYm8NwS9ThNuZRpWtyNQLLMPzTw4qadjbSEj 3 53
yzvEZ287fSq17edR6SoCPLW3yVvt41GqFMahcra2iDVkWociU4Gg5a0CjtKKbiXE 4 55
yzvEZ287f2S9LHweGmqqpgFqfZ1Ce67N99p06sibzY96mpJnGmwpLZZ6Ek7pbUVN 5 54
yzvEZ287fG8AaccKhG3mxg1zxXx4yZtYskDPJHKtRi3u4FyDAqnd9GNQAghMdyxy 6 50
yzvEZ287fiZWGJm3jPqCwqCLnvin8gLsKv55vDYJYH49VxZaorYX0dUx7bCid8j7 7 54
yzvEZ287fQ5ZtP8zFQ3qTWa0TVcctBJ30mnUP0qfHzh6ehoupkbecr4zY1REd60B 8 54
yzvEZ287fobiJpexmqWmruNjyDhZfUat6f4LqM5YTTNT5w7LYTFMjXW3MAA34fLw 9 55


We could predict the next character by looking at the Levenstein distance on the right.

The final answer is: