2022NCTF


2022NCTF

这次Crypto题目对于我来说过于困难,还好战队的佬写了wp

Coloratura

题目

attach

from Crypto.Util.number import long_to_bytes
from PIL import Image, ImageDraw
from random import getrandbits

width = 208
height = 208
flag = open('flag.txt').read()


def makeSourceImg():
    colors = long_to_bytes(getrandbits(width * height * 24))[::-1]
    img = Image.new('RGB', (width, height))
    x = 0
    for i in range(height):
        for j in range(width):
            img.putpixel((j, i), (colors[x], colors[x + 1], colors[x + 2]))
            x += 3
    return img


def makeFlagImg():
    img = Image.new("RGB", (width, height))
    draw = ImageDraw.Draw(img)
    draw.text((5, 5), flag, fill=(255, 255, 255))
    return img


if __name__ == '__main__':
    img1 = makeSourceImg()
    img2 = makeFlagImg()
    img3 = Image.new("RGB", (width, height))
    for i in range(height):
        for j in range(width):
            p1, p2 = img1.getpixel((j, i)), img2.getpixel((j, i))
            img3.putpixel((j, i), tuple([(p1[k] ^ p2[k]) for k in range(3)]))
    img3.save('attach.png')

解题脚本

from PIL import Image

def inverse_shift(x, shift, type, mask=0xffffffff, nbit=32):
    res = x
    for _ in range(nbit//shift):
        if type == 'l': res = x ^ res << shift & mask
        if type == 'r': res = x ^ res >> shift & mask
    return res
def crack_extract(x):
    x = inverse_shift(x, 18, 'r')
    x = inverse_shift(x, 15, 'l', 4022730752)
    x = inverse_shift(x,  7, 'l', 2636928640)
    x = inverse_shift(x, 11, 'r')
    return x
def crack_twist(cur):
    high = 0x80000000
    low = 0x7fffffff
    mask = 0x9908b0df
    state = cur
    for i in range(623,-1,-1):
        tmp = state[i]^state[(i+397)%624]
        # recover Y,tmp = Y
        if tmp & high == high:
            tmp ^= mask
            tmp <<= 1
            tmp |= 1
        else:
            tmp <<=1
        # recover highest bit
        res = tmp&high
        # recover other 31 bits,when i =0,it just use the method again it so beautiful!!!!
        tmp = state[i-1]^state[(i+396)%624]
        # recover Y,tmp = Y
        if tmp & high == high:
            tmp ^= mask
            tmp <<= 1
            tmp |= 1
        else:
            tmp <<=1
        res |= (tmp)&low
        state[i] = res
    return state
def extract(x):
    y = x
    y = y ^ y >> 11
    y = y ^ y << 7 & 2636928640
    y = y ^ y << 15 & 4022730752
    y = y ^ y >> 18
    return y

width = 208
height = 208
img3 = Image.open('attach.png')
out = []
for i in range(height):
    for j in range(width):
        pix = img3.getpixel((j, i))
        out += [pix[0], pix[1], pix[2]]

out = [hex(_)[2:].zfill(2) for _ in out][::-1]
out = ''.join(out)
now_rand = [out[i: i + 8] for i in range(0, len(out), 8)][::-1]
now_rand = [int(_, 16) for _ in now_rand]

state = [crack_extract(_) for _ in now_rand[-624:]]
ini_rand = []
while len(ini_rand) < len(now_rand):
    ini_rand = [extract(_) for _ in state] + ini_rand
    state = crack_twist(state)

ini_rand = [hex(_)[2:].zfill(8) for _ in ini_rand][::-1]
ini_rand = ''.join(ini_rand)
ini = [ini_rand[i: i + 2] for i in range(0, len(ini_rand), 2)][::-1]
ini = [int(_, 16) for _ in ini]

x = 0
flag = Image.new('RGB', (width, height))
for i in range(height):
    for j in range(width):
        pix = img3.getpixel((j, i))
        flag.putpixel((j, i), (pix[0] ^ ini[x], pix[1] ^ ini[x + 1], pix[2] ^ ini[x + 2]))
        x += 3
flag.show()

image-20230314213110239

dp_promax

题目

from Crypto.Util.number import *
from random import *


nbits = 2200
beta = 0.4090
p, q = getPrime(int((1. - beta) * nbits)), getPrime(int(beta * nbits))
dp = getrandbits(50) | 1
while True:
    d = (p - 1) * getrandbits(2800) + dp
    if GCD((p - 1) * (q - 1), d) == 1:
        break
e = inverse(d, (p - 1) * (q - 1))
N = p * q
flag = bytes_to_long(open('flag.txt', 'rb').read())

c = pow(flag, e, N)
print(N)
print(e)
print(c)

"""
46460689902575048279161539093139053273250982188789759171230908555090160106327807756487900897740490796014969642060056990508471087779067462081114448719679327369541067729981885255300592872671988346475325995092962738965896736368697583900712284371907712064418651214952734758901159623911897535752629528660173915950061002261166886570439532126725549551049553283657572371862952889353720425849620358298698866457175871272471601283362171894621323579951733131854384743239593412466073072503584984921309839753877025782543099455341475959367025872013881148312157566181277676442222870964055594445667126205022956832633966895316347447629237589431514145252979687902346011013570026217
13434798417717858802026218632686207646223656240227697459980291922185309256011429515560448846041054116798365376951158576013804627995117567639828607945684892331883636455939205318959165789619155365126516341843169010302438723082730550475978469762351865223932725867052322338651961040599801535197295746795446117201188049551816781609022917473182830824520936213586449114671331226615141179790307404380127774877066477999810164841181390305630968947277581725499758683351449811465832169178971151480364901867866015038054230812376656325631746825977860786943183283933736859324046135782895247486993035483349299820810262347942996232311978102312075736176752844163698997988956692449
28467178002707221164289324881980114394388495952610702835708089048786417144811911352052409078910656133947993308408503719003695295117416819193221069292199686731316826935595732683131084358071773123683334547655644422131844255145301597465782740484383872480344422108506521999023734887311848231938878644071391794681783746739256810803148574808119264335234153882563855891931676015967053672390419297049063566989773843180697022505093259968691066079705679011419363983756691565059184987670900243038196495478822756959846024573175127669523145115742132400975058579601219402887597108650628746511582873363307517512442800070071452415355053077719833249765357356701902679805027579294
"""

发现N可以分解

import gmpy2
import libnum
e = 13434798417717858802026218632686207646223656240227697459980291922185309256011429515560448846041054116798365376951158576013804627995117567639828607945684892331883636455939205318959165789619155365126516341843169010302438723082730550475978469762351865223932725867052322338651961040599801535197295746795446117201188049551816781609022917473182830824520936213586449114671331226615141179790307404380127774877066477999810164841181390305630968947277581725499758683351449811465832169178971151480364901867866015038054230812376656325631746825977860786943183283933736859324046135782895247486993035483349299820810262347942996232311978102312075736176752844163698997988956692449
c = 28467178002707221164289324881980114394388495952610702835708089048786417144811911352052409078910656133947993308408503719003695295117416819193221069292199686731316826935595732683131084358071773123683334547655644422131844255145301597465782740484383872480344422108506521999023734887311848231938878644071391794681783746739256810803148574808119264335234153882563855891931676015967053672390419297049063566989773843180697022505093259968691066079705679011419363983756691565059184987670900243038196495478822756959846024573175127669523145115742132400975058579601219402887597108650628746511582873363307517512442800070071452415355053077719833249765357356701902679805027579294
p=3628978044425516256252147348112819551863749940058657194357489608704171827031473111609089635738827298682760802716155197142949509565102167059366421892847010862457650295837231017990389942425249509044223464186611269388650172307612888367710149054996350799445205007925937223059
q=12802692475349485610473781287027553390253771106432654573503896144916729600503566568750388778199186889792482907407718147190530044920232683163941552482789952714283570754056433670735303357508451647073211371989388879428065367142825533019883798121260838408498282273223302509241229258595176130544371781524298142815099491753819782913040582455136982147010841337850805642005577584947943848348285516563
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,p*q)
print(libnum.n2s(int(m)))
#nctf{Th1s_N_May_n0t_s0@o0@@_secur3}

superecc

题目

from Crypto.Util.number import *
from secrets import INF, flag

assert flag[:5] == b'nctf{'


class super_ecc:
    def __init__(self):
        self.a = 73101304688827564515346974949973801514688319206271902046500036921488731301311
        self.c = 78293161515104296317366169782119919020288033620228629011270781387408756505563
        self.d = 37207943854782934242920295594440274620695938273948375125575487686242348905415
        self.p = 101194790049284589034264952247851014979689350430642214419992564316981817280629

    def add(self, P, Q):
        (x1, y1) = P
        (x2, y2) = Q
        x3 = (x1 * y2 + y1 * x2) * inverse(self.c * (1 + self.d * x1 * x2 * y1 * y2), self.p) % self.p
        y3 = (y1 * y2 - self.a * x1 * x2) * inverse(self.c * (1 - self.d * x1 * x2 * y1 * y2), self.p) % self.p
        return (x3, y3)

    def mul(self, x, P):
        Q = INF
        x = x % self.p
        while x > 0:
            if x % 2 == 1:
                Q = self.add(Q, P)
            P = self.add(P, P)
            x = x >> 1
        return Q


flag = bytes_to_long(flag[5:-1])
ecc = super_ecc()
G = (30539694658216287049186009602647603628954716157157860526895528661673536165645,
     64972626416868540980868991814580825204126662282378873382506584276702563849986)
S = ecc.mul(flag, G)
print(S)
# (98194560294138607903211673286210561363390596541458961277934545796708736630623,
# 58504021112693314176230785309962217759011765879155504422231569879170659690008)

脚本

考查的是Twisted Edward Curve

题⽬定义了⼀个循环群上的点加法,搜索可以发现是Twisted Edward Curve

img

经过适当的变化可以将c消除掉,得到标准形式

img

对于Twisted Edward Curve,可以转化为等价的Montgomery Curve

img

Montgomery Curve的形式已经是Weierstrass形式的椭圆曲线,可以使⽤sage求解其阶,即求得了Twisted Edward Curve的阶寻找阶中的⼩素数因⼦,使⽤Pohlig Hellman + BSGS求解离散对数问题,得到flag的值

#!/usr/bin/env sage
class super_ecc:
    def __init__(self):
        self.a = 73101304688827564515346974949973801514688319206271902046500036921488731301311
        self.c = 78293161515104296317366169782119919020288033620228629011270781387408756505563
        self.d = 37207943854782934242920295594440274620695938273948375125575487686242348905415
        self.p = 101194790049284589034264952247851014979689350430642214419992564316981817280629
        self.INF = (0, self.c)

    def add(self, P, Q):
        (x1, y1) = P
        (x2, y2) = Q
        x3 = (x1 * y2 + y1 * x2) * inverse_mod(self.c * (1 + self.d * x1 * x2 * y1 * y2), self.p) % self.p
        y3 = (y1 * y2 - self.a * x1 * x2) * inverse_mod(self.c * (1 - self.d * x1 * x2 * y1 * y2), self.p) % self.p
        return (x3, y3)

    def mul(self, x, P):
        Q = self.INF
        x = x % self.p
        while x > 0:
            if x % 2 == 1:
                Q = self.add(Q, P)
            P = self.add(P, P)
            x = x >> 1
        return Q

def get_order():
    d = d * c^4 % p
    A = 2 * (a + d) * inverse_mod(a - d, p) % p
    B = 4 * inverse_mod(a - d, p) % p
    a1 = 0
    a3 = 0
    a2 = A*B%p
    a4 = B*B%p
    a6 = 0
    E=EllipticCurve(GF(p),[a1,a2,a3,a4,a6])
    np=E.cardinality()
    return ZZ(np)

ecc = super_ecc()

from tqdm import tqdm
def Pohlig_Hellman(L, R, sub_order, order):
    def add(P, Q):
        return ecc.add(P, Q)
    def mul(P, x):
        return ecc.mul(x % order, P)
    def BSGS(L, R, sub):
        L, R = mul(L, (order//sub)), mul(R, (order//sub))

        m, dic = sqrt(sub).round(), dict()
        ga = mul(L, 0)
        for i in tqdm(range(m + 1)):
            dic[str(ga)], ga = i, add(ga, L)
        gb = mul(L, (-m))
        for i in tqdm(range(sub//m + 1)):
            if str(R) in dic:
                sk = i*m + dic[str(R)]
                print(f"{sub} -> {sk}")
                return ZZ(sk)
            R = add(R, gb)
        return None

    sk = crt(
        [BSGS(L, R, sub) for sub in sub_order],
        sub_order
    )
    return sk

# order = get_order()
order = 101194790049284589034264952247851014979635478581961323247248565451562534055248
sub_order = [16, 113, 28921, 749971, 87374629]
G = (30539694658216287049186009602647603628954716157157860526895528661673536165645,
     64972626416868540980868991814580825204126662282378873382506584276702563849986)
S = (98194560294138607903211673286210561363390596541458961277934545796708736630623,
     58504021112693314176230785309962217759011765879155504422231569879170659690008)

sk = Pohlig_Hellman(G, S, sub_order, order)
from Crypto.Util.number import *
print(long_to_bytes(sk))

文章作者: f14g
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 f14g !
评论
  目录