记一次 caibi 在这场比赛中的记录.....cry 拿了 两一血 一二血都没有进 crypto rk 前三... 太菜了... 最后还是压线 rk 15 太菜拉!

要努力!

<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>

# Web:

EZ_Game :

F12 审计代码,直接改 health 还有个啥 arrow 无敌!

# Misc:

冰冰好像藏着秘密 :

下载下来说头文件有病... 去查 没问题.... 试试看把后面 ihdr 后面的复制出来? 结果真可以.... 然后卡 了很久查了 LSB 无果.... 然后发现这个 RAR 叫做 FFT,百度 傅里叶变换.. 查了一会说是 音频?? 然后 再查查看 png? 结果出来了 网上有脚本。就是装库真麻烦.....

# Crypto:

White give:

先看题,一开始我是想把 hint 用在了指数上去操作... 想了一个多点没想法... 然后发现这 娃意 phi 上面这个 p 是可以整出来的。好活! 那就出来了...

然后是 url 进去 看题..emm short pad attack 前几天刚整理了一下... 还是不太懂这个时间多项式的意思,借用 tb 师傅 exp 过了

from gmpy2 import*
from Crypto.Util.number import*
c = 
s = 
n1= 
e=0x10001
e1=pow(e,e,n1)
c1=e1*s
p=gcd(c1-1,n1)
q=n1//(p*p)
phi1=p*(p-1)*(q-1)
d=inverse(e,phi1)
e=pow(c,d,n1)
print(e)
n=
c=
e=
'''发现e很大 使用维纳不行,那就博纳试试
import time
debug = True
strict = False
helpful_only = True
dimension_min = 7 
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii,ii] >= modulus:
            nothelpful += 1
    print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print(a)
# delete the unhelpful vectors
# we start at current = n-1 
def remove_unhelpful(BB, monomials, bound, current):
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB
    for ii in range(current, -1, -1):
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
            for jj in range(ii + 1, BB.dimensions()[0]):
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj
            # task 0
            if affected_vectors == 0:
                print("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii-1)
                return BB
            # task 1
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
                    print("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii-1)
                    return BB
    return BB
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
    PR.<u, x, y> = PolynomialRing(ZZ)
    Q = PR.quotient(x*y + 1 - u) # u = xy + 1
    polZ = Q(pol).lift()
    UU = XX*YY + 1
    # x-shifts
    gg = []
    for kk in range(mm + 1):
        for ii in range(mm - kk + 1):
            xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
            gg.append(xshift)
    gg.sort()
    monomials = []
    for polynomial in gg:
        for monomial in polynomial.monomials():
            if monomial not in monomials:
                monomials.append(monomial)
    monomials.sort()
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
            yshift = Q(yshift).lift()
            gg.append(yshift) 
    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            monomials.append(u^kk * y^jj)
    # 构造 lattice 
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0, 0)
        for jj in range(1, ii + 1):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
    if helpful_only:
        BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
        nn = BB.dimensions()[0]
        if nn == 0:
            print("failure")
            return 0,0
    if debug:
        helpful_vectors(BB, modulus^mm)
    det = BB.det()
    bound = modulus^(mm*nn)
    if det >= bound:
        print("We do not have det < bound. Solutions might not be found.")
        print("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
    if debug:
        matrix_overview(BB, modulus^mm)
    # LLL
    if debug:
        print("optimizing basis of the lattice via LLL, this can take a long time")
    BB = BB.LLL()
    if debug:
        print("LLL is done!")
    if debug:
        print("looking for independent vectors in the lattice")
    found_polynomials = False
    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
            PR.<w,z> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
                pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)
            # resultant
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break
    if not found_polynomials:
        print("no independant vectors could be found. This should very rarely happen...")
        return 0, 0
    rr = rr(q, q)
    # solutions
    soly = rr.roots()
    if len(soly) == 0:
        print("Your prediction (delta) is too small")
        return 0, 0
    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]
    return solx, soly
def main():
    N = 
    # the public exponent
    e = 
    # the hypothesis on the private exponent (the theoretical maximum is 0.292)
    delta = 0.25 # this means that d < N^delta
    # Lattice (tweak those values)
    # you should tweak this (after a first run), (e.g. increment it until a solution is found)
    m = 4 # size of the lattice (bigger the better/slower)
    # you need to be a lattice master to tweak these
    t = int((1-2*delta) * m)  # optimization from Herrmann and May
    X = 2*floor(N^delta)  # this _might_ be too much
    Y = floor(N^(1/2))    # correct if p, q are ~ same size
    # Don't touch anything below
    # Problem put in equation
    P.<x,y> = PolynomialRing(ZZ)
    A = int((N+1)/2)
    pol = 1 + x * (A + y)
    if debug:
        print("~~~ checking values ~~~")
        print("[*] delta:", delta)
        print("[*] delta < 0.292", delta < 0.292)
        print("[*] size of e:", int(log(e)/log(2)))
        print("[*] size of N:", int(log(N)/log(2)))
        print("[*] m:", m, ", t:", t)
    # boneh_durfee
    if debug:
        print("~~~ running ~~~ ")
        start_time = time.time()
    solx, soly = boneh_durfee(pol, e, m, t, X, Y)
    # found a solution?
    if solx > 0:
        print("~~~ [!] found ~~~")
        if False:
            print("x:", solx)
            print("y:", soly)
        d = int(pol(solx, soly) / e)
        print("private key found:", d)
    else:
        print("[!][!][!] no solution was found ...")
    if debug:
        print("=== %s seconds ===" % (time.time() - start_time))
if __name__ == "__main__":
    main()
'''
d=
print(long_to_bytes(pow(c,d,n)))
'''
def short_pad_attack(c1, c2, e, n):
    PRxy.<x,y> = PolynomialRing(Zmod(n))
    PRx.<xn> = PolynomialRing(Zmod(n))
    PRZZ.<xz,yz> = PolynomialRing(Zmod(n))
    g1 = x^e - c1
    g2 = (x+y)^e - c2
    q1 = g1.change_ring(PRZZ)
    q2 = g2.change_ring(PRZZ)
    h = q2.resultant(q1)
    h = h.univariate_polynomial()
    h = h.change_ring(PRx).subs(y=xn)
    h = h.monic()
    kbits = n.nbits()//(2*e*e)
    diff = h.small_roots(X=2^kbits, beta=0.4)[0]  # find root < 2^kbits with factor >= n^0.4
    return diff
def related_message_attack(c1, c2, diff, e, n):
    PRx.<x> = PolynomialRing(Zmod(n))
    g1 = x^e - c1
    g2 = (x+diff)^e - c2
    def gcd(g1, g2):
        while g2:
            g1, g2 = g2, g1 % g2
        return g1.monic()
    return -gcd(g1, g2)[0]
if __name__ == '__main__':
    n = 
    e = 7
    c1 =
    c2 = 
    diff = short_pad_attack(c1, c2, e, n)
    print("difference of two messages is %d" % diff)
    m1 = related_message_attack(c1, c2, diff, e, n)
    print("m1:", m1)
    print("m2:", m1 + diff)
    '''
m=
print(long_to_bytes(m))

Strange Function:

然后去获取数据。发现 1.0 的数据都很大 。看代码,里面是 ord / 这个数。是个 random 出来的数,那就可以 data 的 + 1 去剪,然后就可以发现。很接近他自然的 ord 1.0 五关就过了

2.0 的话就是发现他变小了,一开始我想着改四舍五入的进制,甚至开了 n 个脚本一起跑.... 结果没过一个 xswl... 然后想到 这些 ascii 码值,用概率去分析他大概是多少。然后去加减... 但是也不能保证百分百 所以 就让他如果断了就自动重连!

from pwn import*
import string
from hashlib import*
from math import*
def pow():
    io.recvuntil('XXXX')
    str1=io.recvuntil(b"== ")[1:-5]
    sha=io.recvuntil('\n')[:-1]
    for i in a:
        for j in a:
            for k in a:
                for m in a:
                    stringa=i+j+k+m+str(str1,encoding='utf-8')
                    has=sha256(stringa.encode()).hexdigest()
                    if bytes(has,encoding='utf8')==sha:
                        io.sendline(i+j+k+m)
                        return 1
def getdata():
    io.recvuntil("?\n")
    io.recvuntil("[")
    data=[]
    for i in range(7):
        data.append(int(io.recvuntil(",")[:-1]))
    data.append(int(io.recvuntil("]")[:-1]))
    print(data)
    return data
def getdata2(n):
    io.recvuntil("win!\n[!]")
    io.recvuntil("[")
    data=[]
    for i in range(n*8+7):
        data.append(int(io.recvuntil(",")[:-1]))
    data.append(int(io.recvuntil("]")[:-1]))
    print(data)
    return data
def task1():
    charr=''
    for i in range(len(data)):
        io.sendline("1")
        io.recvuntil("x: \n[-]")
        io.sendline(str(data[i]+1).encode())
        io.recvuntil("answer:")
        num=(float(io.recvuntil("\n")[:-1]))
        cha=0
        for j in range(len(data)):
            if j==i :
                continue
            cha += 85/(data[i]-data[j])
        num=round(num-cha)
        io.recvuntil("[-]")
        charr+=(chr(num))
    print(charr)
    return charr
def task2():
    io.sendline("2")
    io.recvuntil("[-]")
    io.sendline(charr)
if __name__=="__main__":
    a=string.ascii_letters+string.digits
    while 1:
        try:
            io=remote("127.0.0.1",28735)
            pow()
            data=getdata()
            charr=task1()
            task2()
            for i in range(4):
                    data=getdata2(i+1)
                    charr=task1()
                    task2()
            io.recvuntil("flag")
            flag=b'flag'+io.recvuntil("}")
            print(flag)
            break
        except:
            continue
    io.interactive()

Factor:

这道题没写出来... 赛后复现...

审题, 特点:两组公钥 加密相同的信息。一开始我是想把他列出来 ... 但是我合到一起变成了只有一个方程。问题是我并没有把 shallow 上次说让我们记忆的那条式子是干啥的并不清楚 55555555 看了 Wp 之后发现还有一条 需要 上界 即

SVP12n14det(L)1n||SVP_1||≤2^{\frac{n-1}{4}}det(L)^{\frac{1}{n}}

SVP1ndet(L)1n||SVP_1||≤\sqrt{n}det(L)^{\frac{1}{n}}

即取一个 M 大于 SVP<sub>1</sub>, 而由于 N<sub>1</sub> < N<sub>2</sub> < 2 N<sub>1</sub>,d 是 300 位 N 是 1024 位 因此 上界可以取 M = 根号 (N<sub>2</sub>) 同时三维向量

(d,k1s1+1,k2s1+1)=d2+(k1s1+1)2+(k2s2+1)2||(d,k1s1+1,k2s1+1)||=\sqrt{d^2+(k_1s_1+1)^2+(k_2s_2+1)^2}

2600+21600+21600>det([1,e1,e2][0,N1,0][0,0,N2])13≈\sqrt{2^{600}+2^{1600}+2^{1600}}>det({[1,e_1,e_2][0,-N_1,0][0,0,-N_2]})^{\frac{1}{3}}

为了使得他们差不多大小,因此取 M = 根号 N2 在中间则使得他的 dM 值需要接近于 21600 使得超过上界一点(其中 s<sub>1</sub>=notPhi1-N1 , s2=notPhi2-N2

from Crypto.Util.number import*
from gmpy2 import*
pubkeys = [(, ), (, )]
cs = (, )
(N1,e1) = pubkeys[0]
(N2,e2) = pubkeys[1]
c1 = cs[0]
c2 = cs[1]
M = #iroot(N2,2)[0]
'''
A=Matrix(ZZ,[[M,e1,e2],[0,-N1,0],[0,0,-N2]])
A.LLL()
'''
d= A.LLL()[0][0] //M
kkk1=  A.LLL()[0][1]           
kkk2=  A.LLL()[0][2]
#d e1-k1 N1=1+k1 s1=kkk1
k1=(d*e1-kkk1)//N1
k2=(d*e2-kkk2)//N2
s1=(kkk1-1)//k1-1
s2=(kkk2-1)//k2-1
ss1=iroot(s1*s1-4*N1,2)[0]
p1=(ss1+s1)//2
q1=s1-p1
ss2=iroot(s2*s2-4*N2,2)[0]
p2=(ss2+s2)//2
q2=s2-p2
d1=inverse(e1,(p1-1)*(q1-1))
d2=inverse(e2,(p2-1)*(q2-1))
print(long_to_bytes(pow(c1,d1,N1)))
printlong_to_bytes(pow(c2,d2,N2)))

请我喝[茶]~( ̄▽ ̄)~*

De3B4to 微信支付

微信支付

De3B4to 支付宝

支付宝