from Crypto.Util.number import *
from Crypto.PublicKey import RSA
from hashlib import sha256
import random, os, signal, string
def proof_of_work():
random.seed(os.urandom(8))
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
_hexdigest = sha256(proof.encode()).hexdigest()
print(f"sha256(XXXX+{proof[4:]}) == {_hexdigest}")
print('Give me XXXX: ')
x = input()
if len(x) != 4 or sha256(x.encode()+proof[4:].encode()).hexdigest() != _hexdigest:
print('Wrong PoW')
return False
return True
if not proof_of_work():
exit(1)
signal.alarm(10)
print("Give me a bad RSA keypair.")
try:
p = int(input('p = '))
q = int(input('q = '))
assert p > 0
assert q > 0
assert p != q
assert p.bit_length() == 512
assert q.bit_length() == 512
assert isPrime(p)
assert isPrime(q)
n = p * q
e = 65537
assert p % e != 1
assert q % e != 1
d = inverse(e, (p-1)*(q-1))
except:
print("Invalid params")
exit(2)
try:
key = RSA.construct([n,e,d,p,q])
print("This is not a bad RSA keypair.")
exit(3)
except KeyboardInterrupt:
print("Hacker detected.")
exit(4)
except ValueError:
print("How could this happen?")
from secret import flag
print(flag)
按照 brealid 师傅的推导过程自己推了一遍
工作量证明 模板
import hashlib
import string
import itertools
from tqdm import tqdm
from pwn import *
# 遍历所有的XXXX,找到符合条件的XXXX
b = string.digits + string.ascii_letters + string.punctuation
strL = itertools.product(b, repeat=4)
ip = '47.93.187.243'
port = 39092
io = remote(ip, port, level='debug')
data = io.recvline()
# print(data) # b'sha256(XXXX+2ywKnEOsDsVMJXvP) == f8ffb979f1819dba9905c67b9b85874c681807f6e3cb2953901785764f5e8db8\n'
残缺的sha = data.split(b'+')[1].split(b')')[0]
sha256后的值 = data.split(b'== ')[1].strip()
hash_object = hashlib.sha256()
for i in strL:
a = i[0] + i[1] + i[2] + i[3]
sha = a + 残缺的sha.decode()
# print(sha)
hash_object.update(sha.encode())
digest = hash_object.digest()
hex_digest = digest.hex()
if hex_digest == sha256后的值.decode():
print(a)
io.sendline(a.encode())
break
io.interactive()
推导
brealid 师傅的exp
from Crypto.Util.number import *
from pwn import remote
import sys
e = 65537
while True:
p = getPrime(512)
m = inverse(e, p - 1)
temp = (e * m * p - 1) // (p - 1) # k(q - 1)
for k in range(1, e + 1):
if temp % k == 0:
q = temp // k + 1
if isPrime(q) and q.bit_length() == 512:
print('[+] Found Answer')
print('[+] p:', p)
print('[+] q:', q)
sys.exit(0)
完整exp
import hashlib
import itertools
from string import digits, ascii_letters, punctuation
from pwn import remote
from Crypto.Util.number import *
import sys
alpha_bet = digits+ascii_letters+punctuation
strlist = itertools.product(alpha_bet, repeat=4)
ip = 'node4.anna.nssctf.cn'
port = 28537
io = remote(ip, port, level='debug')
# sha256(XXXX+NxsXxwrH2UPagm3m) == 94641f7dff7a461fa93291607a6eb6eb0525f5173667150da77b95406503fc1a\n
data = io.recvline()
sha256后的值 = data.split(b'== ')[1].strip()
print('[+]sha256后的值: ', sha256后的值.decode())
残缺的sha = data.split(b'+')[1].split(b')')[0]
print('[+]残缺的sha: ', 残缺的sha.decode())
xxxx = ''
from time import sleep
from tqdm import tqdm
for i in tqdm(strlist):
data = i[0]+i[1]+i[2]+i[3]
data_sha = hashlib.sha256(
(data+str(残缺的sha, encoding='utf-8')).encode('utf-8')).hexdigest()
# print(data_sha)
# print(data+str(tail,encoding='utf-8'))
# sleep(10)
if(data_sha == str(sha256后的值, encoding='utf-8')):
xxxx = data
break
print('[+]XXXX: ', xxxx)
io.sendline(xxxx.encode())
# io.recvall() #接收数据,直到达到EOF
# io.recv() #接收数据
# io.recvline() #接收一行数据
# io.recvuntil() # 接收到指定的内容后停止接收
# io.recvregex() # 接收到指定的正则表达式后停止接收
# io.recvrepeat() # 接收数据,直到超时
e = 65537
"""
check = False
while not check:
p = getPrime(512)
m = inverse(e, p - 1)
temp = (e * m * p - 1) // (p - 1) # k(q - 1)
for k in range(1, e + 1):
if temp % k == 0:
q = temp // k + 1
if isPrime(q) and q.bit_length() == 512:
print('[+] Found Answer')
print('[+] p:', p)
print('[+] q:', q)
check = True
# io.recvuntil(b'p = ')
# sleep(0.1)
# io.sendline(str(p).encode())
# sleep(0.1)
# io.recvuntil(b'q = ')
# # io.interactive()
# sleep(0.1)
# io.sendline(str(q).encode())
# io.interactive()
# break
sys.exit(0) # import sys
"""
# 不知道为什么用上面代码生成的pq直接传回大概率会报错(加了sleep也不行) 但是用预先生成好的pq就不会出错 有大佬知道原因的话麻烦告诉我一下
p = '8488801046431263229761805441065431376077145677248462075865125669622031730090796088901063330271972848555387039635408118509976679229257625394609078671892933'
q = '10075063365346849262583010629024489954242128039849695882991747768104067285864791682013796650024431727893076443223174478213078909720566236635993645492116989'
io.recvuntil(b'p = ')
io.sendline(p.encode())
io.recvuntil(b'q = ')
io.sendline(q.encode())
io.interactive()