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整个加密过程,会发现
phi和n很接近,那么公式可以改写成
此时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程序就行(不能写太多怕被官方开盒