2023羊城杯-CRY-复盘!

1.[羊城杯 2023]Danger_RSA

题目:

from Crypto.Util.number import *

m = bytes_to_long(flag)


def get_key(a, nbit):
    assert a >= 2
    while True:
        X = getRandomInteger(nbit // a)
        s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
        p = X ** a + s
        if isPrime(p):
            return (p, s)


p, s = get_key(a, 1024)
q, t = get_key(a, 1024)

N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
# e = 11079917583
# c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766

解题过程:上次hgjj给了我一点思路,但是还是铸币没做出来,就是观察p,q的生成过程,发现x是一个(nbits//a)位的数字,s是一个a^2-a+5位的数字,p=x^a+s.p和q都是由同一个a生成的,e又等于s*t,那么e的位数是34,s和t的位数就是17,a就是4,那我们知道s和t的位数,就可以根据e分解出来的因子爆破s和t了

x = [3, 7, 7, 19, 691, 5741]
c = 1
num = set()

for j in range(1, 7):
    for i in itertools.product(x, repeat=j):
        p = c * reduce(mul, i)
        if p.bit_length() == 17:
            num.add(p)

print(num)

根据这个生成s和t的所有可能性,根据n=p*q解二元一次方程组

n = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
e = 11079917583
data=[68229, 130599, 101577, 123823, 120561, 118161, 130321, 117649, 109079, 91903]
ab=int(gmpy2.iroot(n,4)[0])
print(ab)
date=[i for i in itertools.combinations(data,2)]
for s,t in date:
    if s*t!=e:
        continue
    var('a b')
    f1=ab==a*b
    f2=n==(a**4+s)*(b**4+t)
    tmp=solve([f1,f2],[a,b])
    print(tmp)
    print(s,t)

解出p,q和s,t后又因为e不是素数,我们要用AMM算法解出最后的m

import random
import time
from tqdm import tqdm
from Crypto.Util.number import *
# About 3 seconds to run
def AMM(o, r, q):
    start = time.time()
    print('\n----------------------------------------------------------------------------------')
    print('Start to run Adleman-Manders-Miller Root Extraction Method')
    print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q))
    g = GF(q)
    o = g(o)
    p = g(random.randint(1, q))
    while p ^ ((q-1) // r) == 1:
        p = g(random.randint(1, q))
    print('[+] Find p:{}'.format(p))
    t = 0
    s = q - 1
    while s % r == 0:
        t += 1
        s = s // r
    print('[+] Find s:{}, t:{}'.format(s, t))
    k = 1
    while (k * s + 1) % r != 0:
        k += 1
    alp = (k * s + 1) // r
    print('[+] Find alp:{}'.format(alp))
    a = p ^ (r**(t-1) * s)
    b = o ^ (r*alp - 1)
    c = p ^ s
    h = 1
    for i in range(1, t):
        d = b ^ (r^(t-1-i))
        if d == 1:
            j = 0
        else:
            print('[+] Calculating DLP...')
            j = - discrete_log(d, a)
            print('[+] Finish DLP...')
        b = b * (c^r)^j
        h = h * c^j
        c = c^r
    result = o^alp * h
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    print('Find one solution: {}'.format(result))
    return result

def onemod(p,r): 
    t=random.randint(2,p)
    while pow(t,(p-1)//r,p)==1: 
         t=random.randint(2,p)
    return pow(t,(p-1)//r,p) 
 
def solution(p,root,e):  
    while True:
        g=onemod(p,e) 
        may=[] 
        for i in tqdm(range(e)): 
            may.append(root*pow(g,i,p)%p)
        if len(may) == len(set(may)):
            return may


def solve_in_subset(ep,p):
    cp = int(pow(c,inverse(int(e//ep),p-1),p))
    com_factors = []
    while GCD(ep,p-1) !=1:
        com_factors.append(GCD(ep,p-1))
        ep //= GCD(ep,p-1)
    com_factors.sort()

    cps = [cp]
    for factor in com_factors:
        mps = []
        for cp in cps:
            mp = AMM(cp, factor, p)
            mps += solution(p,mp,factor)
        cps = mps
    for each in cps:
        assert pow(each,e,p)==c%p
    return cps

p = 3891889986375336330559716098591764128742918441309724777337583126578227827768865619689858547513951476952436981068109005313431255086775128227872912287517417948310766208005723508039484956447166240210962374423348694952997002274647622939970550008327647559433222317977926773242269276334110863262269534189811138319
q = 5213351003420231819415242686664610206224730148063270274863722096379841592931572096469136339538500817713355302889731144789372844731378975059329731297860686270736540109105854515590165681366189003405833252270606896051264517339339578167231093908235856718285980689179840159807651185918046198419707669304960745217
c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766


ep = 49
eq = 3

m_p = solve_in_subset(49,p)
m_q = solve_in_subset(3,q)

for mpp in m_p:
    for mqq in m_q: 
        m = crt([int(mpp),int(mqq)],[p,q])
        flag = long_to_bytes(m)
        if b'CTF' in flag:
            print(flag)
            break

得到flag:DASCTF{C0nsTruct!n9_Techn1qUe2_f0r_RSA_Pr1me_EnC2ypt10N}

2.[羊城杯 2023]esyRSA

from gmpy2 import invert
from md5 import md5
from secret import p, q

e = ?????
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)

print n, e, d
print "Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest()

"""
n = 8064259277274639864655809758868795854117113170423331934498023294296505063511386001711751916634810056911517464467899780578338013011453082479880809823762824723657495915284790349150975180933698827382368698861967973964030509129133021116919437755292590841218316278732797712538885232908975173746394816520256585937380642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""


这里发现e是一个五位的数字,然后我们仔细回想一下RSA整个加密过程,会发现e*d=1(mod phi)

e*d=k*phi+1

\frac{d}{phi}-\frac{k}{e}=\frac{1}{e*phi}

phi和n很接近,那么公式可以改写成

\frac{d}{n}-\frac{k}{e}=\frac{1}{e*phi}

此时phi特别大,我们可把他视作0,所以d/n=k/e,对d/n进行连分数展开就可以求出这个e

from Crypto.Util.number import *
from gmpy2 import *

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

c = continued_fraction(d/n)
for i in range(1, 100):
    k = int(c.numerator(i)) # 分子
    e = int(c.denominator(i))
    
    if (e * d - 1) % k==0:
        print(k)
        print(e)
        p_q = n + 1 - (e * d - 1) // k
        print('p + q =', p_q)

求出之后逆向一下就行

3.PYCODE

百忙之中补一道逆向题目

  0           0 RESUME                   0

  1           2 LOAD_CONST               0 (0)
              4 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (base64)
              8 STORE_NAME               0 (base64)

  2          10 LOAD_CONST               2 ('*******************')
             12 STORE_NAME               1 (flag)

  3          14 LOAD_CONST               3 ('')
             16 STORE_NAME               2 (value)

  4          18 LOAD_CONST               3 ('')
             20 STORE_NAME               3 (output)

  5          22 PUSH_NULL
             24 LOAD_NAME                4 (range)
             26 LOAD_CONST               4 (1000)
             28 PRECALL                  1
             32 CALL                     1
             42 GET_ITER
        >>   44 FOR_ITER                24 (to 94)
             46 STORE_NAME               5 (i)

  6          48 LOAD_CONST               5 (1024)
             50 STORE_NAME               6 (w)

  7          52 LOAD_NAME                6 (w)
             54 LOAD_CONST               6 (3)
             56 BINARY_OP                6 (%)
             60 STORE_NAME               7 (x)

  8          62 LOAD_NAME                6 (w)
             64 LOAD_CONST               7 (9)
             66 BINARY_OP                2 (//)
             70 STORE_NAME               8 (y)

  9          72 LOAD_NAME                7 (x)
             74 LOAD_NAME                8 (y)
             76 BINARY_OP                5 (*)
             80 STORE_NAME               9 (z)

 10          82 LOAD_NAME                6 (w)
             84 LOAD_NAME                9 (z)
             86 BINARY_OP               23 (-=)
             90 STORE_NAME               6 (w)
             92 JUMP_BACKWARD           25 (to 44)

 11     >>   94 PUSH_NULL
             96 LOAD_NAME                4 (range)
             98 LOAD_CONST               8 (10000)
            100 PRECALL                  1
            104 CALL                     1
            114 GET_ITER
        >>  116 FOR_ITER                24 (to 166)
            118 STORE_NAME               5 (i)

 12         120 LOAD_CONST               9 (20)
            122 STORE_NAME               6 (w)

 13         124 LOAD_NAME                6 (w)
            126 LOAD_CONST              10 (6)
            128 BINARY_OP                6 (%)
            132 STORE_NAME               7 (x)

 14         134 LOAD_NAME                6 (w)
            136 LOAD_CONST               6 (3)
            138 BINARY_OP                2 (//)
            142 STORE_NAME               8 (y)

 15         144 LOAD_NAME                7 (x)
            146 LOAD_NAME                8 (y)
            148 BINARY_OP                5 (*)
            152 STORE_NAME               9 (z)

 16         154 LOAD_NAME                6 (w)
            156 LOAD_NAME                9 (z)
            158 BINARY_OP               13 (+=)
            162 STORE_NAME               6 (w)
            164 JUMP_BACKWARD           25 (to 116)

 17     >>  166 PUSH_NULL
            168 LOAD_NAME                4 (range)
            170 LOAD_CONST               4 (1000)
            172 PRECALL                  1
            176 CALL                     1
            186 GET_ITER
        >>  188 FOR_ITER                24 (to 238)
            190 STORE_NAME               5 (i)

 18         192 LOAD_CONST               5 (1024)
            194 STORE_NAME               6 (w)

 19         196 LOAD_NAME                6 (w)
            198 LOAD_CONST               6 (3)
            200 BINARY_OP                6 (%)
            204 STORE_NAME               7 (x)

 20         206 LOAD_NAME                6 (w)
            208 LOAD_CONST               7 (9)
            210 BINARY_OP                2 (//)
            214 STORE_NAME               8 (y)

 21         216 LOAD_NAME                7 (x)
            218 LOAD_NAME                8 (y)
            220 BINARY_OP                5 (*)
            224 STORE_NAME               9 (z)

 22         226 LOAD_NAME                6 (w)
            228 LOAD_NAME                9 (z)
            230 BINARY_OP               23 (-=)
            234 STORE_NAME               6 (w)
            236 JUMP_BACKWARD           25 (to 188)

 23     >>  238 PUSH_NULL
            240 LOAD_NAME                4 (range)
            242 LOAD_CONST               8 (10000)
            244 PRECALL                  1
            248 CALL                     1
            258 GET_ITER
        >>  260 FOR_ITER                24 (to 310)
            262 STORE_NAME               5 (i)

 24         264 LOAD_CONST               9 (20)
            266 STORE_NAME               6 (w)

 25         268 LOAD_NAME                6 (w)
            270 LOAD_CONST              10 (6)
            272 BINARY_OP                6 (%)
            276 STORE_NAME               7 (x)

 26         278 LOAD_NAME                6 (w)
            280 LOAD_CONST               6 (3)
            282 BINARY_OP                2 (//)
            286 STORE_NAME               8 (y)

 27         288 LOAD_NAME                7 (x)
            290 LOAD_NAME                8 (y)
            292 BINARY_OP                5 (*)
            296 STORE_NAME               9 (z)

 28         298 LOAD_NAME                6 (w)
            300 LOAD_NAME                9 (z)
            302 BINARY_OP               13 (+=)
            306 STORE_NAME               6 (w)
            308 JUMP_BACKWARD           25 (to 260)

 29     >>  310 PUSH_NULL
            312 LOAD_NAME                4 (range)
            314 LOAD_CONST               0 (0)
            316 PUSH_NULL
            318 LOAD_NAME               10 (len)
            320 LOAD_NAME                1 (flag)
            322 PRECALL                  1
            326 CALL                     1
            336 PRECALL                  2
            340 CALL                     2
            350 GET_ITER
        >>  352 FOR_ITER                38 (to 430)
            354 STORE_NAME               5 (i)

 30         356 LOAD_NAME                1 (flag)
            358 LOAD_NAME                5 (i)
            360 BINARY_SUBSCR
            370 STORE_NAME              11 (temp)

 31         372 PUSH_NULL
            374 LOAD_NAME               12 (chr)
            376 PUSH_NULL
            378 LOAD_NAME               13 (ord)
            380 LOAD_NAME               11 (temp)
            382 PRECALL                  1
            386 CALL                     1
            396 LOAD_CONST              11 (8)
            398 BINARY_OP               12 (^)
            402 PRECALL                  1
            406 CALL                     1
            416 STORE_NAME              11 (temp)

 32         418 LOAD_NAME                2 (value)
            420 LOAD_NAME               11 (temp)
            422 BINARY_OP               13 (+=)
            426 STORE_NAME               2 (value)
            428 JUMP_BACKWARD           39 (to 352)

 33     >>  430 PUSH_NULL
            432 LOAD_NAME                4 (range)
            434 PUSH_NULL
            436 LOAD_NAME               10 (len)
            438 LOAD_NAME                1 (flag)
            440 PRECALL                  1
            444 CALL                     1
            454 PRECALL                  1
            458 CALL                     1
            468 GET_ITER
        >>  470 FOR_ITER                38 (to 548)
            472 STORE_NAME               5 (i)

 34         474 LOAD_NAME                2 (value)
            476 LOAD_NAME                5 (i)
            478 BINARY_SUBSCR
            488 STORE_NAME              11 (temp)

 35         490 PUSH_NULL
            492 LOAD_NAME               12 (chr)
            494 PUSH_NULL
            496 LOAD_NAME               13 (ord)
            498 LOAD_NAME               11 (temp)
            500 PRECALL                  1
            504 CALL                     1
            514 LOAD_CONST               6 (3)
            516 BINARY_OP                0 (+)
            520 PRECALL                  1
            524 CALL                     1
            534 STORE_NAME              11 (temp)

 36         536 LOAD_NAME                3 (output)
            538 LOAD_NAME               11 (temp)
            540 BINARY_OP               13 (+=)
            544 STORE_NAME               3 (output)
            546 JUMP_BACKWARD           39 (to 470)

 37     >>  548 PUSH_NULL
            550 LOAD_NAME                0 (base64)
            552 LOAD_ATTR               14 (b64encode)
            562 LOAD_NAME                3 (output)
            564 LOAD_METHOD             15 (encode)
            586 PRECALL                  0
            590 CALL                     0
            600 PRECALL                  1
            604 CALL                     1
            614 LOAD_METHOD             16 (decode)
            636 PRECALL                  0
            640 CALL                     0
            650 STORE_NAME              17 (obfuscated_output)

 38         652 LOAD_NAME               17 (obfuscated_output)
            654 LOAD_CONST               1 (None)
            656 LOAD_CONST               1 (None)
            658 LOAD_CONST              12 (-1)
            660 BUILD_SLICE              3
            662 BINARY_SUBSCR
            672 STORE_NAME              17 (obfuscated_output)

 39         674 LOAD_NAME               17 (obfuscated_output)
            676 LOAD_METHOD             18 (replace)
            698 LOAD_CONST              13 ('0')
            700 LOAD_CONST              14 ('t')
            702 PRECALL                  2
            706 CALL                     2
            716 STORE_NAME              17 (obfuscated_output)

 40         718 LOAD_NAME               17 (obfuscated_output)
            720 LOAD_METHOD             18 (replace)
            742 LOAD_CONST              15 ('c')
            744 LOAD_CONST              16 ('4')
            746 PRECALL                  2
            750 CALL                     2
            760 STORE_NAME              17 (obfuscated_output)

 41         762 LOAD_NAME               17 (obfuscated_output)
            764 LOAD_METHOD             18 (replace)
            786 LOAD_CONST              17 ('+')
            788 LOAD_CONST              18 ('-')
            790 PRECALL                  2
            794 CALL                     2
            804 STORE_NAME              17 (obfuscated_output)

 42         806 PUSH_NULL
            808 LOAD_NAME               19 (print)
            810 LOAD_NAME               17 (obfuscated_output)
            812 PRECALL                  1
            816 CALL                     1
            826 POP_TOP
            828 LOAD_CONST               1 (None)
            830 RETURN_VALUE

==AeAF3M-tzO-giQ-AUQosDQ9tGK7MDPuhC47tDNB5Tb8Yn4sdW4

这里LOAD_NAME就是变量名,PUSH_NULL就代表一个循环的开始,一直逆向出这个py程序就行(不能写太多怕被官方开盒

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值