#!/usr/bin/python from functools import reduce with open("flag", "r") as f: key = [ord(x) for x in f.read().strip()] def substitute(value): return (reduce(lambda x, y: x * value + y, key)) % 691 print("Enter a number and it will be returned with our super secret synthetic substitution technique") while True: try: value = input("> ") if value == 'quit': quit() value = int(value) enc = substitute(value) print(">> ", end="") print(enc) except ValueError: print("Invalid input. ")
((k1 * value + k2) * value + k3) ...
という感じで、k1, k2, ...
を求める
もう少し書き直して、実はこうで、を好きに指定できる
例えば となるようなを見つけることができれば……これはですが、今回modは素数なのでこういう値はない
雑に次のようなLLLで解けないだろうか。でもこれだとどういうを選ぶのが良いのだろう
……とか無駄なことを考えていたが、何回でもリクエストできるのだから、フラグの長さをとして個の式を建てて連立方程式を解けば良い。実際にはより長くしても余った変数が0でうまるので何でも良い。剰余連立方程式を行列で解く
from ptrlib import Socket M = 691 for k in range(5, 50, 5): sock = Socket("crypto.2021.chall.actf.co", 21601) # sock = Socket("localhost", 19999) X = [] Y = [] for i in range(1, k+1): xs = [i^j % M for j in range(k)][::-1] X.append(xs) sock.sendlineafter("> ", str(i)) y = int(sock.recvlineafter(">> ")) Y.append(y) X = matrix(Zmod(M), X) Y = matrix(Zmod(M), Y).transpose() recovered = list(X.solve_right(Y).transpose())[0] try: print(repr(bytes(recovered))) except: print(recovered) sock.close()