The server checks the password attaches the flag and several word to it, gzip it, encrypts it with aes in cbc mode and sends it us back. The encryption seems to be implemented well, and full decryption of the CT seems to be impossible. But since the answer with our password and the flag is compressed before encryption, we have a little information leakage channel though the size of CT.If there's same substring in our password and in the flag, then the answer would be compressed better; the longer the substring is the better the compression would be. This way we can recover the flag char by char.We try all printable charaters by sending'hxp{' + c + n_random_characters, wherec is the character we tryn_random_characters - string of random characters of length n.If we choose n properly, then we'll get shorter answer for the right character c, then for any other. (lenght of CT of aes_cbc is multiple of 16 bytes, we need to choose n such that the length of compressed answer would be at the edge between blocks)So, the listing:import socketimport osimport stringflag = b'hxp{' def rand_chars(n):    s = ''    for i in range(n):        c = chr(os.urandom(1)[0])        while c == ' ' or c == '\n' or c not in string.printable:            c = chr(os.urandom(1)[0])        s += c    return s.encode()def get_ans_len(pwd):    sock = socket.socket()    sock.connect(('131.159.74.81', 1033))    sock.send(pwd + b' a\n')    ans = sock.recv(4096)    return len(ans)len_to_send = 28def check_flag(flag_beg, chars_to_verify):  # checks which letter from chars_to_verify is the next letter of flag_beg    global len_to_send    while len(chars_to_verify) > 1:        print("Verifying charset: %s" % chars_to_verify)        lens = {}        suf = rand_chars(len_to_send - len(flag_beg) - 1)        for c in chars_to_verify:            lens[c] = get_ans_len(flag_beg + c.encode() + suf)        print(lens)        if min(lens.values()) == max(lens.values()):  # we need to tune len_to_send to get back to the edge between cipher blocks            if min(lens.values()) <= 289:                len_to_send += 1                print("increased len: %u" % len_to_send)            else:                len_to_send -= 1                 print("decreased len: %u" % len_to_send)        for c in lens.keys():            if lens[c] > min(lens.values()):                chars_to_verify = chars_to_verify.replace(c, '')    print(flag_beg + chars_to_verify[0].encode())    return chars_to_verify[0].encode()while flag[-1] != b'}':    c = check_flag(flag, string.ascii_letters + string.digits + '_}')  # .replace('\n', '').replace(' ', ''))    flag += cAnd the flag:hxp{1_r34LLy_L1k3_0r4cL3s__n0T_7h3_c0mp4nY}