# 卷王杯

# 密码签到

密文: Y3NldHRfZl9jc2FyaF95b3Nwd2l0JTdCbW9qcCF1bCU3RA==

base64 解码 csett_f_csarh_yospwit%7Bmojp!ul%7D

url 解码 csett_f_csarh_yospwit{mojp!ul}

栅栏爆破 ctfshow{just_a_simple_crypto!}

# 真・简单・不卷・现代密码签到

from Crypto.Util.number import bytes_to_long
from secrets import p,q,r,s,t,flag
n = p * q * r * s * t
e = 2
m = bytes_to_long(os.urandom(500) + flag)
c = pow(m,e,n)
print(p,q,r,s,t,sep='\n')
print(c)
'''
145332367700944303747548912160113939198078051436029477960348968315913956664143693347226702600438608693933768134575289286283267810723137895903153829001826223446477799895493265422562348917012216790077395795861238257357035152687833639085415763850743538206986781418939737511715957738982536382066693822159860701263
116660458253067608044065523310547233337730583902133756095473339390057738510707447906971188577217274861047379404014140178165569604404468897712846876108444468370709141219302291601408652742006268186059762087155933131837323952675627966299810891805398890428420575425160696531236660480933905879208166090591482794763
157931722402853245421436270609912823260313730941283152856444641969403238646482562190531038393124087232554754746464603598717356255570166081501573727336977292059427220330169044611674973569766966838498453232642731737958791706086957762244686953294662693939604300864961637325536379321027705854708492453330690705531
100973451687449518854742673778783266158999451072058606348222018797891147675959983616210003484476577612134482311993701677242007759556951494382833070563369964294544839433671087037596159753825249018950693369209927951667775267086896180395776150188902057785214767230658487267587289809918132337927575673868568976679
93960345071948255233882121683650797512129333868351496468898834736770441398743300745703393838320587998953678254272245400344928586394089488734271897540051673996675973642347859306921527430850673334243441180183460927865980713929789963587608547554858491264614271309608925634272282292964002897650355047792764365447
9144597920381774885442906257311149465702295057238600973973598305004391534618770363098565074541384771979931799878381439264848137810353858418200992191234142740194489573540381681161219332611454834544291634628456257670178843484698324641739324687497388018406214041657278323855749902661752448796122517061920880552011343608609622885787617238758769398972009949575526258430282648817039091284796330585349957724522615105102735930258969562103112238020133587096826386028128471852377225525357348919204333121695432662339443004327748973224423132988376298843862056631045488285859621661802413201793962883794915513510467912312842687601478117040419013468059983777273699192408773551806581458197324620065210523913467414181480875280203580147077789063808832356486197271376615883221558265591069223727607585313240243619515521180600435114131162272519949101464089935441251751426683447701142156416866113627126765919641034042927519834229168536331952275698122511502745177547569813354280565828372968703810158857859460406828090199683324760956105682902577189283246483314689365570862217407333103243336691401424548702387876409228977278498691200028282744239512091373110111792177228979867318546462714521296256938374618636206565791541769138267080789842400796973226733816939794717596194090232425688504890234304977612220790858557639246367437740975495450011676714198668471438814299689325208882261918460708833888406187912527346628912894921059735420931656953236560178909180587372589456926690219114173193202048332172538564489660440225377822914097420807957784201785024166011709377791129
'''

e=2 可以想到 rabin 但是 gcd (e,p-1)=e,gcd (e,q-1)=e……

看到 la 佬博客里有

AMM 算法看不懂加 CRT 算法

p=145332367700944303747548912160113939198078051436029477960348968315913956664143693347226702600438608693933768134575289286283267810723137895903153829001826223446477799895493265422562348917012216790077395795861238257357035152687833639085415763850743538206986781418939737511715957738982536382066693822159860701263
q=116660458253067608044065523310547233337730583902133756095473339390057738510707447906971188577217274861047379404014140178165569604404468897712846876108444468370709141219302291601408652742006268186059762087155933131837323952675627966299810891805398890428420575425160696531236660480933905879208166090591482794763
r=157931722402853245421436270609912823260313730941283152856444641969403238646482562190531038393124087232554754746464603598717356255570166081501573727336977292059427220330169044611674973569766966838498453232642731737958791706086957762244686953294662693939604300864961637325536379321027705854708492453330690705531
s=100973451687449518854742673778783266158999451072058606348222018797891147675959983616210003484476577612134482311993701677242007759556951494382833070563369964294544839433671087037596159753825249018950693369209927951667775267086896180395776150188902057785214767230658487267587289809918132337927575673868568976679
t=93960345071948255233882121683650797512129333868351496468898834736770441398743300745703393838320587998953678254272245400344928586394089488734271897540051673996675973642347859306921527430850673334243441180183460927865980713929789963587608547554858491264614271309608925634272282292964002897650355047792764365447
c=9144597920381774885442906257311149465702295057238600973973598305004391534618770363098565074541384771979931799878381439264848137810353858418200992191234142740194489573540381681161219332611454834544291634628456257670178843484698324641739324687497388018406214041657278323855749902661752448796122517061920880552011343608609622885787617238758769398972009949575526258430282648817039091284796330585349957724522615105102735930258969562103112238020133587096826386028128471852377225525357348919204333121695432662339443004327748973224423132988376298843862056631045488285859621661802413201793962883794915513510467912312842687601478117040419013468059983777273699192408773551806581458197324620065210523913467414181480875280203580147077789063808832356486197271376615883221558265591069223727607585313240243619515521180600435114131162272519949101464089935441251751426683447701142156416866113627126765919641034042927519834229168536331952275698122511502745177547569813354280565828372968703810158857859460406828090199683324760956105682902577189283246483314689365570862217407333103243336691401424548702387876409228977278498691200028282744239512091373110111792177228979867318546462714521296256938374618636206565791541769138267080789842400796973226733816939794717596194090232425688504890234304977612220790858557639246367437740975495450011676714198668471438814299689325208882261918460708833888406187912527346628912894921059735420931656953236560178909180587372589456926690219114173193202048332172538564489660440225377822914097420807957784201785024166011709377791129
e=2
P.<a>=PolynomialRing(Zmod(p),implementation='NTL')
f=a^e-c
mpx=f.monic().roots()
P.<a>=PolynomialRing(Zmod(q),implementation='NTL')
g=a^e-c
mqx=g.monic().roots()
P.<a>=PolynomialRing(Zmod(r),implementation='NTL')
h=a^e-c
mrx=h.monic().roots()
P.<a>=PolynomialRing(Zmod(s),implementation='NTL')
i=a^e-c
msx=i.monic().roots()
P.<a>=PolynomialRing(Zmod(t),implementation='NTL')
j=a^e-c
mtx=j.monic().roots()
for mpp in mpx:
    x=mpp[0]
    for mqq in mqx:
        y=mqq[0]
        for mrr in mrx:
            z=mrr[0]
            for mss in msx:
                a=mss[0]
                for mtt in mtx:
                    b=mtt[0]
                    solution=hex(CRT_list([int(x),int(y),int(z),int(a),int(b)], [p,q,r,s,t]))[2:]
                    if (b'ctfshow'.hex() in solution):
                        print(bytes.fromhex(solution))

#

from Crypto.Cipher import AES
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
import random
def woohoo():
    a = random.getrandbits(32)
    b = random.getrandbits(32)
    c = random.getrandbits(32)
    d = random.getrandbits(32)
    return (a<<96)+(b<<64)+(c<<32)+(d)
BANNER = """
+-------------+
|    *   *    |
|    *   *    |
| *********** |
|    *   *    |
|             |
|  *********  |
|      *      |
|     *       |
| *********** |
|    *  *     |
|    *  *     |
|   *   *   * |
| **    ***** |
+-------------+
赛事预告: 
比赛名称:ctfshow 卷王杯 
题目难度:无 
出题奖励:usb小台灯+周边钥匙扣 
比赛奖励:单项第1送定制妹子贴纸,单项AK取前3 
比赛时间:2022年2月25日(周五) 18时整 
比赛时长:48小时 
比赛地址:https://ctf.show/challenges 
投稿邮箱:ctfshow@163.com
"""
MENU = """
+-----------------+
|[E]ncrypt        |
|[T]est encryption|
|[8]86            |
+-----------------+
"""
if __name__ == '__main__':
    print(BANNER)
    # 我只泄露一点线索
    # 是谁为爱走钢索
    for i in range(130):
        print(MENU)
        option = input("> ").lower()
        if option == "e":
            print("Enter your message.")
            msg = input("> ").encode()
            msg = pad(msg, AES.block_size)
            key = woohoo()
            iv = woohoo()
            key = long_to_bytes(key).rjust(AES.block_size, b"\x00")
            iv = long_to_bytes(iv).rjust(AES.block_size, b"\x00")
            
            c = AES.new(key, AES.MODE_CBC, iv=iv)
            ct = c.encrypt(msg)
            
            iv = b"never gonna give you up"
            
            print(f"Ciphertext (hex): {ct.hex()}")
            print(f"Key (hex): {key.hex()}")
            print(f"IV (hex): {iv.hex()}")
        elif option == "t":
            flag = open("flag.txt", "rb").read()
            msg = pad(flag, AES.block_size)
            key = woohoo()
            iv = woohoo()
            key = long_to_bytes(key)
            iv = long_to_bytes(iv)
            
            c = AES.new(key, AES.MODE_CBC, iv=iv)
            ct = c.encrypt(msg)
            
            key = b"never gonna let you down"
            
            print(f"Ciphertext (hex): {ct.hex()}")
            print(f"Key (hex): {key.hex()}")
            print(f"IV (hex): {iv.hex()}")
        elif option == "8":
            print("Sa yo na la!")
            break
        else:
            print("What r u DOIN?")
    else:
        print("Never gonna run around and desert you")

我们可以看到

def woohoo():
    a = random.getrandbits(32)
    b = random.getrandbits(32)
    c = random.getrandbits(32)
    d = random.getrandbits(32)
    return (a<<96)+(b<<64)+(c<<32)+(d)

看到 getrandbits 就要想到 mt19937 随机数预测

在选项 e 里 可以得到 key 值

那么通过这个值可以得到密文解密后的明文 1 在与自己设置的 iv 异或得到正真的 iv

具体可以看图
AES解密

这样我们知道了 key 和 iv 就相当于知道了 8 个随机数

而成功预测要 624 个 所以要 624/8 次循环

from pwn import *
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from mt19937predictor import MT19937Predictor
re=remote("pwn.challenge.ctf.show",28046)
mt=[]
for i in range(100):
    m=b''
    re.recvuntil(b'> ')
    re.sendline(b'E')
    re.recvuntil(b'> ')
    re.sendline(m)
    re.recvuntil(b'Ciphertext (hex): ')
    c = int(re.recv(32).decode(), 16)
    re.recvuntil(b'Key (hex): ')
    key1 = int(re.recv(32).decode(), 16)
    mt.append(key1)
    c=long_to_bytes(c).rjust(AES.block_size, b"\x00")
    key1=long_to_bytes(key1).rjust(AES.block_size, b"\x00")
    iv0=b'\x00'*16
    d=AES.new(key1,AES.MODE_CBC,iv0)
    iv=d.decrypt(c).rjust(AES.block_size, b"\x00")
    iv1=bytes_to_long(xor(iv,pad(m,AES.block_size)))
    mt.append(iv1)
predictor = MT19937Predictor ()
for i in mt:
    d=i & (2**32-1)
    i=i>>32
    c=i &(2**32-1)
    i=i>>32
    b = i & (2 ** 32 - 1)
    i = i >> 32
    a = i & (2 ** 32 - 1)
    predictor.setrandbits(a, 32)
    predictor.setrandbits(b, 32)
    predictor.setrandbits(c, 32)
    predictor.setrandbits(d, 32)
a=predictor.getrandbits(32)
b=predictor.getrandbits(32)
c=predictor.getrandbits(32)
d=predictor.getrandbits(32)
key=(a<<96)+(b<<64)+(c<<32)+(d)
a=predictor.getrandbits(32)
b=predictor.getrandbits(32)
c=predictor.getrandbits(32)
d=predictor.getrandbits(32)
iv=(a<<96)+(b<<64)+(c<<32)+(d)
print(hex(iv))
key = long_to_bytes(key)
iv = long_to_bytes(iv)
re.recvuntil(b'> ')
re.sendline(b'T')
c=int(re.recvline().decode().strip()[18:],16)
c=long_to_bytes(c)
h = AES.new(key, AES.MODE_CBC, iv)
print(h.decrypt(c))
re.interactive()

# 概率 RSA

完全没思路,看了 wp and 借鉴 307 的博客

la 佬

这道题是 rsa 的 lsb

假设存在一个 oracle,能对给定密文进行解密并给出对应明文的奇偶信息,则我们只需要 log (N) 次就能解密任意密文。

在一次 RSA 加密中,明文为 m,模数为 n,加密指数为 e,密文为 c。我们可以构造出

c′=((2e)⋅c)%n=((2e)⋅(me))%n=((2⋅m)e)%n ,

因为 m 的两倍可能大于 n,所以经过解密得到的明文是 m′=(2⋅m)% n 。

我们还能够知道 m′ 的最低位 lsb 是 1 还是 0。 因为 n 是奇数,而 2⋅m 是偶数,所以如果 lsb 是 0,说明 (2⋅m)% n 是偶数,没有超过 n,即 m<n/2,反之则 m>n/2 。举个例子就能明白 2%3=2 是偶数,而 4%3=1 是奇数。以此类推,构造密文 c′′=((4^e)⋅c)% n 使其解密后为 m′′=(4⋅m)% n ,判断 的奇偶性可以知道 m′′ 和 n/4 的大小关系。所以我们就有了一个二分算法,可以在对数时间内将 m 的范围逼近到一个足够狭窄的空间。

# https://introspelliam.github.io/2018/03/27/crypto/RSA-Least-Significant-Bit-Oracle-Attack/
from pwn import *
from Crypto.Util.number import *
import re
p=remote("pwn.challenge.ctf.show",28158)
# context.log_level = 'debug'
def oracle(c):
    l = []
    for i in range(20):
        p.sendline(str(c))
        s = p.recvuntil(b"temp_c = ")
        l.append(int(re.findall(b"\)\s*=\s*([0-9]*)", s)[0]))
    flag0 = 0
    flag2 = 0
    for i in range(20):
        if l[i] % 2 != 0:
            flag0 = 1
        if l[i] > 10000:
            flag2 = 1
    return [flag2, flag0]
def main():
    ss = p.recvuntil(b"temp_c = ")
    N = int(re.findall(b"N\s*=\s*(\d+)", ss)[0])
    e = int(re.findall(b"e\s*=\s*(\d+)", ss)[0])
    C = int(re.findall(b"c\s*=\s*(\d+)", ss)[0])
    print("N=", N)
    print("e=", e)
    print("c=", C)
    c = (pow(2, e, N) * C) % N
    LB = 0
    UB = N
    i = 1
    while LB != UB:
        flag = oracle(c)
        print(i, flag)
        if flag[1] % 2 == 0:
            UB = (LB + UB) // 2
        else:
            LB = (LB + UB) // 2
        c = (pow(2, e, N) * c) % N
        i += 1
    print(LB)
    print(UB)
    for i in range(-128, 128):
        temp = LB
        temp += i
        if pow(temp, e, N) == C:
            print(long_to_bytes(temp))
            exit(0)
if __name__ == '__main__':
    main()
    p.interactive()

跑的有点慢 要 i=1024 才出来

# 铱锡锡

本题和上次 ECC 一样,漏洞点还是在输入椭圆曲线上的点坐标时,并未检测点是否在曲线上。

并且注意,倍点运算的过程中并未利用到bb 的值进行计算。

所以就有我们可以调整bb 的值,使得点PP 在以我们调整的bb 值所对应的椭圆曲线上。由倍点计算过程,点QQ 也在这条椭圆曲线上。

而且题目给了 6 次尝试机会,所以我们可以把点PP 弄成一个光滑的循环子群的生成元,其阶为nin_i(光滑),送到交互里面,会吐出一个QQ,这样就可以由 Pohlig-Hellman 算法算出kmodnik \bmod n_i 的值。

再由中国剩余定理,如果这些nin_i 选择得当,那么便可以知道kk 的值。

参考的bb 值:1, 4, 12, 38.

#sage
from pwn import *
from sage.all import *
oi=remote('pwn.challenge.ctf.show',28044)
B=[1,5,9,12,38,13]
G=((111400716329737223151348215591382049163897085784802947255747133622415879105394, 39992761736411400081935771079229874378216016675324636692947348968013201165276),
(13719045388076151520803368351989304615465812259733704032402319532249511403233, 70112205679957371132763956439647700048310284796833596573793277095178113815519),
(43073418371286323595156732037737293646818329128791009438524376324397773820726, 35593429086189375972008488132929667910986330958314594350096901828426497889077),
(66433977671962939100073201807983167264694941590643124947273042440494792218015, 21652151330053975273880197568657021519050157521775125899551963970572483258486),
(40092374358375676891557996696416077109395130857602600253780368444671153878383, 1220793250473451325744127538413666357546316742399446078249755026290349789846),
(37673718832712137809127078277795630388877581750162566803210280135148912394288, 56746642413640372892023989284505332312846604225559347665409782919856416362427))
QQ=[]
for i in range(6):
    oi.sendline('1')
    oi.sendline(str(G[i]))
    oi.recvuntil('The coordinate of Q is ')
    x=int(oi.recvuntil(', ')[1:-2])
    y=int(oi.recvuntil('\n')[:-2])
    QQ.append((x,y))
tt=[1,1,2,2,2,1]
aa=[]
bb=[]
for i in range(6):
    print(i)
    p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
    a = -3
    b=B[i]
    E=EllipticCurve(GF(p),[a,b])
    Q=E(QQ[i])
    GG=E(G[i])
    factors, exponents = zip(*factor(E.order()))
    primes = [factors[i] ** exponents[i] for i in range(len(factors))][:-tt[i]]
    K=[]
    mul=1
    for i in primes:
        mul*=i
    for i in primes:
        t=E.order()//i
        k=discrete_log(t*Q,t*GG,operation='+')
        K.append(k)
    aa.append(crt(K,primes))
    bb.append(mul)
print(aa)
print(bb)
pay=crt(aa,bb)
print(pay)
oi.sendline('2')
oi.sendline(str(pay))
oi.interactive()
更新于 阅读次数