from Crypto.Util.number import getPrime,bytes_to_long import time,urandom from flag import flag iv=bytes_to_long(urandom(256)) assert len(flag)==15 keystream=bin(int(flag.encode('hex'),16))[2:].rjust(8*len(flag),'0') p=getPrime(1024) q=getPrime(1024) n=p*q print "n:",n cnt=0 while True: try: print 'give me a number:' m=int(raw_input()) except: break ct=iv for i in range(1,8): if keystream[cnt]=='1': ct+=pow(m^q,i**i**i,n) ct%=n cnt=(cnt+1)%len(keystream) print "done:",ct
15バイトのフラグからkey streamを作った上で、key streamの値によって を計算してくれる。
のとき、となるので、かと思いきや、にはが含まれているのでこれはうまく行かない。しかしとかいうなまえのくせに教えてもらえない割に固定なので、2回やって減算すればの影響を打ち消せて、RSAパートがわかってしまえば7bit全探索するだけ
from ptrlib import Socket from Crypto.Util.number import isPrime import math from itertools import product import proofofwork # sock = Socket("localhost", 9999) sock = Socket("52.163.228.53", 8081) a, b = sock.recvregex(r"sha256\(xxxx\+(.+?)\) == (.+)") s = proofofwork.sha256(b.decode(),text=b"????"+a) sock.sendlineafter("xxxx:", s[:4]) print("[+] pass the PoW") n = int(sock.recvlineafter("n: ")) sock.sendlineafter("number:\n", "0") c1 = int(sock.recvlineafter("done: ")) sock.sendlineafter("number:\n", "0") c2 = int(sock.recvlineafter("done: ")) q = math.gcd(n, (c1 - c2) % n) assert isPrime(q) p = n // q phi = (p-1)*(q-1) print("[+] p:{}".format(p)) print("[+] q:{}".format(q)) sock.sendlineafter("number:\n", str(q)) c3 = int(sock.recvlineafter("done: ")) iv = c3 pos = 21 plaintext = [None for _ in range(120)] while True: # 7bit bruteforce table = {} for bits in product([0,1], repeat=7): ct = iv for j, b in enumerate(bits): if not b: continue i = j + 1 ex = pow(i, i**i, phi) ct += pow(2, ex, n) ct = ct % n table[ct] = bits sock.sendlineafter("number:\n", str(q^2)) ct = int(sock.recvlineafter("done: ")) for bit in table[ct]: plaintext[pos] = bit pos = (pos + 1) % 120 cnt = len([1 for b in plaintext if b is not None]) print("[+] progress: {}/{}".format(cnt, 120)) if cnt >= 120: break print(plaintext) print(bytes(plaintext))