0%

BUUCTF 每日打卡 2021-8-30

引言

马上开学了,摸了 打了DASCTF八月赛,比赛结束前1小时参赛,结果解题最多的题没做出来(啊这) 在这里插入图片描述

[DASCTF八月赛 2021]easymath

比赛的时候没做出来,后来Pheonix大佬告诉了我解法 给的代码很短:

1
2
3
assert(len(open('flag.txt', 'rb').read()) < 50)
assert(str(int.from_bytes(open('flag.txt', 'rb').read(), byteorder='big') << 10000).endswith(
'1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008'))

做到时候很疑惑,把给的数字转换成二进制也就五百多位,哪来左移10000位呢 也可以有这样的关系式:\(end = flag * 2^{10000}\space mod \space 10^{175}\) 其中175是给的结尾部分的十进制位数,模\(10^{175}\)的目的是为了求\(2^{10000}\)的逆元,得到flag 解密代码如下:

1
2
3
4
5
6
7
from Crypto.Util.number import *

end = 1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008
# end = flag*2**{10000} mod 10^{175}
t = inverse(2**10000, 10**175)
m = long_to_bytes(((end * t) % 10**175) // GCD(2**10000, 10**175))
print(m)

结果为: 在这里插入图片描述 这里值得注意的是,如果用t = gmpy2.invert(2**10000, 10**175),则会报错: 在这里插入图片描述 那为什么用Crypto.Util.number库的inverse就行呢?还有,为什么要除GCD(2**10000, 10**175)呢? 模逆元的定义中有这样一段话: 整数 a 对模数 n 之模逆元存在的充分必要条件是 a 和 n 互素,若此模逆元存在,在模数 n 下的除法可以用和对应模逆元的乘法来达成,此概念和实数除法的概念相同 本题中\(10^{175}\)\(2^{10000}\)显然不互素,inverse先分离出了GCD(2**10000, 10**175),才可以进行模逆元计算,因此最后要除GCD(2**10000, 10**175)

[DASCTF八月赛 2021]let's play with rsa~

加密代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from sympy import isprime,nextprime
from Crypto.Util.number import getPrime as getprime ,long_to_bytes,bytes_to_long,inverse
flag='flag{***************}'

def play():
p=getprime(1024)
q=getprime(1024)

n=p*q
e=65537

print "Hello,let's play rsa~\n"
print 'Now,I make some numbers,wait a second\n'
n1=getprime(200)
n2=getprime(200)
number=n1*n2
print "Ok,i will send two numbers to you,one of them was encoded.\n"
print "Encode n1:%d,\n"%(pow(n1,e,n))
print "And n2:%d.\n"%n2

print "Information that can now be made public:the public key (n,e):(%d,%d)\n"%(n,e)
while True:
try:
c=int(raw_input("ok,now,tell me the value of the number (encode it for safe):"))
except:
print "Sorry,the input is illeagal, and the integer is accept~"
else:
break
d=inverse(e,(p-1)*(q-1))
m=pow(c,d,n)
if m==number:
print "It's easy and interesting,didn't it?\n"
print "This is the gift for you :"+flag
else:
print "Emmmmm,there is something wrong, bye~\n"

if __name__ == '__main__':
play()

先随机生成了两个数n1,n2,然后给了我们pow(n1,e,n)n2,让我们传进去一个c使得c最后RSA解密后与n1*n2相等 那直接把n2加密之后和pow(n1,e,n)相乘,传进去不就行了吗(啊这) 生成c代码如下:

1
2
3
4
5
6
c1 = 
n2 =
n =
e = 65537
c2 = pow(n2, e, n)
print(c1*c2 % n)

把结果传入即可

[DASCTF八月赛 2021]ezRSA

加密代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from secret import flag
from Crypto.Util.number import *
from random import getrandbits
from hashlib import sha256


class EzRsa:
def __init__(self):
self.E = 0x10001
self.P = getPrime(1024)
self.Q = getPrime(1024)
while GCD((self.P-1)*(self.Q-1), self.E) != 1:
self.Q = getPrime(1024)
self.N = self.P*self.Q

def encrypt(self):
f = getrandbits(32)
c = pow(f, self.E, self.N)
return (f, c)

def encrypt_flag(self, flag):
f = bytes_to_long(flag)
c = pow(f, self.E, self.N)
return c


def proof():
seed = getrandbits(32)
print(seed)
sha = sha256(str(seed).encode()).hexdigest()
print(f"sha256({seed>>18}...).hexdigest() = {sha}")
sha_i = input("plz enter seed: ")
if sha256(sha_i.encode()).hexdigest() != sha:
exit(0)


if __name__ == "__main__":
proof()
print("welcome to EzRsa")
print("""
1. Get flag
2. Encrypt
3. Insert
4. Exit
""")
A = EzRsa()
coin = 5
while coin > 0:
choose = input("> ")
if choose == "1":
print(
f"pow(flag,e,n) = {A.encrypt_flag(flag)}\ne = 0x10001")
exit(0)
elif choose == "2":
f, c = A.encrypt()
print(f"plain = {f}\ncipher = {c}")
coin -= 1
elif choose == "3":
q = getrandbits(1024)
n = A.P*q
f = getrandbits(32)
c = pow(f, 0x10001, n)
print(f"plain = {f}\ncipher = {c}")
coin -= 1
elif choose == "4":
print("bye~")
else:
print("wrong input")
print("Now you get the flag right?")

输入1,能得到加密后的flag和e 输入2,用EzRsa中的公钥记为nt,随机加密一个数,得到明文和密文 输入3,用EzRsa中的p和一个随机生成的q生成新的公钥记为nk,随机加密一个数,得到明文和密文 我们可以利用明文,e和密文得到公钥 由于有四次机会,可以得到一对nt和一对nk,由此得到输入2中的\(n1 = gcd(nt1, nt2)\)和输入3中的\(n2 = gcd(nk1, nk2)\),由于n1n2有公因子p,得到\(p = gcd(n1,n2)\),所以可以分解EzRsa中的n,得到flag 至于proof()部分,不知道为什么,他把seed都print出来了,直接复制就行了 解密代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from Crypto.Util.number import *
import gmpy2

ck1 = 10802736552802052334675431350693279487373514975583856720432908395157316583920875453552436496142443616668241018608905018877443641691597372943993746940796864088947110039691619330329829547914610310034042851600736815309651502714085552791205969637596625163884286216655679274373500381744546328590741571307166491219684988090657352142159038206188374695832891006030375956054657085966865212601720744964287594027579678929262839778089899170206998082556473498244863021611505400743727905185153354589976465321853027253539821633361185313034408565005594026376244077003811333923401071515437065293484027335646730805732706266190998912717
mk1 = 3467298486
ck2 = 7952426014817800345542743164212370465256522007694059040467262294139883798321376411423890059270181570060140439911489431487610048706425767050670076985945266595950167706634614499687295626618973683170430839755441335740665931270096392149318526814329218978695464692209823256428215580327499120933284877331428541567646264394511614834203230064225146095541013932153997347325545390454756521012184772766523934716861371813919366599810016530328522084402639154774851578047016291472426451432937369700785642186037817214135023341172743718729742706979406927034574357730393647164709577350234290575266246455335325036550238459460266826777
mk2 = 2637805758
ct1 = 5258297249437233269252734235581546483712740587856019368263741383010451771667214261941296958987255470129584667269164992391194597613632284942804492915958705615338348819026219002542835081068188830987745841778711674448286841103336689060336238552664704124260432965541782948103450178133013110447584887798935485919036836447185053522888046907188507552263118079180956315895262605349789171527309529542909346214121425645357866293754412692643751802750793196774012389022291591637648327944593680206557486483425679654293733112064106916782478544290625173885362276421903124336254498078544284381979906370583318057836106074195007704645
mt1 = 4018514725
ct2 = 2216710613849759291749271001172813296813995296942937937269459242162726262423838768504690540899513401365048563136110961705376280976325200801225641366994647978361247640072336671999168903599506081309580038964520354319361272932687736277969229054373565318758544270975463383927123441762751596885765477383664317818484566431143004646542531904764815747154445292706021915390615940095755639417784345435399786628193680479805174721200711052159068548732143161630778867220968156180570439298242013424813121308759181410582014316563549742660719169563010989100847264028027523510004333399915674385321042096844588069039993247180371045195
mt2 = 3768336235
e = 0x10001
c = 2409589959567577978959459059612176821685774169484662256361511224239193757207995235364470043362762616376254680228672727010474530311597231338182077689977346876997505890770280261284937438407769714519654847286916170373152881118623219276049395838329185415833388821874689670453791866822667341256546099953050403653918769534241514590069310425374668208283548693974017032984604264320169879760335946006653980827443567622501985484127746767154218399238266814865552396320059488020365523603371608242845046716068485196590482585388538864834136370002751749734914128047230447149334621639953462809629563555690666798206156581413136941807

nk1 = pow(mk1, e) - ck1
nk2 = pow(mk2, e) - ck2
n1 = gmpy2.gcd(nk1, nk2)
print(n1)
nt1 = pow(mt1, e) - ct1
nt2 = pow(mt2, e) - ct2
n2 = gmpy2.gcd(nt1, nt2)
print(n2)
p = gmpy2.gcd(n1, n2)
print(p)
print(gmpy2.is_prime(p))
q = n1 // p
print(q)
print(gmpy2.is_prime(q))
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(c, d, p*q)
print(long_to_bytes(m))

在这里插入图片描述 另外,发现Crypto.Util.number中的GCD()函数比gmpy2gcd()计算较大数时慢很多

结语

希望继续坚持