当前位置: 代码迷 >> 综合 >> BUUCTF 打卡7
  详细解决方案

BUUCTF 打卡7

热度:89   发布时间:2023-11-22 18:37:51.0

1.[NPUCTF2020]共 模 攻 击

给出两个代码。先解hint.py(毕竟解出来的东西是提示)。可以看出这里面含有共模攻击,解出c之后,我们就掌握了密文c,模数p,指数(256),再利用sympy.nthroot_mod(c,256,p)解出明文m。

import sympy,gmpy2
from Crypto.Util.number import *
p = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
e1 = 2303413961
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
e2 = 2622163991
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249gcd = gmpy2.gcdext(e1,e2)
s,t = int(gcd[1]),int(gcd[2])
c = (pow(c1,s,n)*pow(c2,t,n))%n
m = sympy.nthroot_mod(c,256,p)
print(long_to_bytes(m))
#b'm.bit_length() < 400'

解出 m.bit_length() < 400。
再看task.py。不知道e1,e2,连共模攻击都用不了。但是e1, e2 = p, q,c1, c2 = pow(m, e1, n), pow(m, e2, n)。

c1 = me1 mod n =mp mod n = mp mod p
c2 = me2 mod n =mq mod n = mq mod q
由费马定理可得
mp = m mod p
mq = m mod q
所以c1 = m mod p , c2 = m mod q 。
好像可以用中国剩余定理,但是p,q未知。
根据c1 = m mod p , c2 = m mod q 推出
c1 - m = t1 * p
c2 - m = t2 * q
两个等式相乘,得到m2 - (c1 + c2 ) * m + c1 * c2 = t1 * t2 * p * q = k * n
即m2 - (c1 + c2 ) * m + c1 * c2 = 0 mod n

大佬说用Sage来解这个方程。
原来这个Sage是一种语言,我还以为是py里的库:)
在线运行sage脚本:sagemath
在这里插入图片描述
解出来的就是m,再进行long_to_bytes(m)即可得出明文
b’verrrrrrry_345yyyyyyy_rsaaaaaaa_righttttttt?’

2.[b01lers2020]safety_in_number

pubkey.pem文件巨大,读取时间真的长。期间为了看一下具体的n,直接卡死了:)(手贱)

with open("pubkey.pem", "r") as f:ciph = RSA.importKey(f.read())
n = ciph.n
e = ciph.e
print(n)
print(e)

解出的n超大,e=65537。根据c = me mod n可以知道,当n远大于me时,只需对c开e次根即可得到m。

import gmpy2
from Crypto.Util.number import *e = 65537
with open("flag.enc", "rb") as f:flag = f.read()c = int.from_bytes(flag, byteorder = 'little')
m = int(gmpy2.iroot(c,e)[0])
print(long_to_bytes(m))
print(long_to_bytes(m)[::-1])

因为读出来的flag时字节串,需要转成数字再开根号,而在子程序enc中,是进行了小端存储(即低位在前,高位在后,汇编中有介绍)
int.from_bytes和int.to_bytes函数介绍

b'}f00Rp_3RutUf!{ftcp'
b'pctf{!fUtuR3_pR00f}'

正如结果所显示的,低位在前,高位在后,正常的解出来是逆过来的,所以要从最后面开始打印。