西湖论剑网络安全技能大赛 2023

虽然没机会参赛,但也还是要复现学习的。

LockByLock

求n可以利用选择明文攻击,两次输入的明文分别为2和4(两倍关系),通过平方再做差求gcd即可;因为e1和e2都大概是50比特长,可以考虑用bsgs来求解,最后还需要共模攻击计算flag。

image

MyErrorLearn

这是一个MIHNP,但可以用二元copper的模板来解。两个式子都是\((s+r_i)(d_i+e_i)\equiv 1\;mod\;p\),把s的系数乘为一样然后消去即可建立模p下的二元<e1,e2>方程,板子求解就行。

# MIHNP
from pwn import *
from Crypto.Util.number import *
import itertools

def small_roots(f, bounds, m=1, d=None):
	if not d:
		d = f.degree()

	R = f.base_ring()
	N = R.cardinality()
	
	f /= f.coefficients().pop(0)
	f = f.change_ring(ZZ)

	G = Sequence([], f.parent())
	for i in range(m+1):
		base = N^(m-i) * f^i
		for shifts in itertools.product(range(d), repeat=f.nvariables()):
			g = base * prod(map(power, f.variables(), shifts))
			G.append(g)

	B, monomials = G.coefficient_matrix()
	monomials = vector(monomials)

	factors = [monomial(*bounds) for monomial in monomials]
	for i, factor in enumerate(factors):
		B.rescale_col(i, factor)

	B = B.dense_matrix().LLL()

	B = B.change_ring(QQ)
	for i, factor in enumerate(factors):
		B.rescale_col(i, 1/factor)

	H = Sequence([], f.parent().change_ring(QQ))
	for h in filter(None, B*monomials):
		H.append(h)
		I = H.ideal()
		if I.dimension() == -1:
			H.pop()
		elif I.dimension() == 0:
			roots = []
			for root in I.variety(ring=ZZ):
				root = tuple(R(root[var]) for var in f.variables())
				roots.append(root)
			return roots

	return []

sh = remote('1.14.71.254',28817)
exec(sh.recvline().strip()[2:])
p = mod
sh.sendline(b'1')
print(sh.recvline())
exec(sh.recvline()[2:].strip())
exec(sh.recvline()[2:].strip())
r1 = r
d1 = d

sh.sendline(b'1')
print(sh.recvline())
exec(sh.recvline()[2:].strip())
exec(sh.recvline()[2:].strip())
r2 = r
d2 = d
print(r1)
print(d1)
print(r2)
print(d2)
P.<e1,e2> = PolynomialRing(Zmod(p))
f = (r1-r2) * (d1+e1)* (d2+e2) - (d2+e2-d1-e1)
print(f)
e1_,e2_ = small_roots(f,[2^246,2^246],m=3)[0]
s = (inverse_mod(int(d1+e1_),p) - r1) % p
sh.sendline(b'2')
print(sh.recvline())
sh.sendline(str(s).encode())
print(sh.recvline())
print(sh.recvline())
# NSSCTF{4ed49415-bdf9-48a2-841f-079c2a3bb8ca}

MyErrorLearnTwice

参考hnp论文的Chapter 7照着造格子就行,NSSCTF上的远程不容易打通,写了个本地的进行验证。

from Crypto.Util.number import *
import random, os
from gmpy2 import *

p = random.getrandbits(1024)
print('> mod =', p)
secret = random.randint(1, p-1)

def XennyOracle():
    while True:
        try:
            r = getPrime(512)
            e = getPrime(328)
            d = invert(secret+r, p) - e
            break
        except:
            continue
    return ZZ(r),ZZ(d),ZZ(e)

samples = [ XennyOracle() for _ in range(15) ]
rs,ds,es = zip(*samples)
    
A = []
B = []
C = []
D = []

n = 15
r0 = rs[0]
d0 = ds[0]
for j in range(1,n):
    A.append(r0 - rs[j])
    B.append(ds[j]*(r0 - rs[j]) + 1)
    C.append(d0*(r0 - rs[j]) - 1)
    D.append(d0*ds[j]*(r0-rs[j])+d0 - ds[j])

n = 14
m = int(p).bit_length()
k = m - 328
mat = [[0 for _ in range(2*n+2)] for _ in range(3*n+2)]
mat[0][0] = 1
for i in range(1,n+2):
    mat[i][i] = 2 ^ (k - m)
for i in range(n+2,2*n+2):
    mat[i][i] = 4 ^ (k - m)

mat1 = [[0 for _ in range(n)] for _ in range(3*n+2)]
for j in range(n):
    mat1[0][j] = D[j]
    
for i in range(1,n+1):
    mat1[i][i-1] = C[i-1]

for j in range(n):
    mat1[n+1][j] = B[j]

for i in range(n+2,2*n+2):
    mat1[i][i-n-2] = A[i-n-2]

for i in range(2*n+2,3*n+2):
    mat1[i][i-2*n-2] = p 

M = matrix(QQ, mat).augment(matrix(QQ,mat1))
print('LLL...')
solve = M.LLL()
for i in solve:
    if i[0] == 1 or i[0] == -1:
        t1 = i[1]
        if t1 < 0 :
            t1 = t1 * (-1)
        e1 = t1 * 2 ^ 328
        print(f'e1={e1}')
        s = (inverse_mod((ds[1] + e1),p) - rs[1]) % p
        if s == secret:
            print('success!')
            break
print('done...')

MyCurveErrorLearn

同样参考hnp论文,造的格和上题十分类似。大致思路就是向server先后发t和-t,然后根据椭圆曲线表达式和点加法构造多项式,主要过程:

image


image


image

posted @ 2023-02-20 23:48  ZimaB1ue  阅读(198)  评论(0编辑  收藏  举报