平台WP · 2023年10月6日

红包题 国庆第二波-blast wp

国庆第二波-blast wp

from Crypto.Util.number import *
from secret import flag, key

tmp_1 = []
for i in flag:
    assert i in [_ for _ in range(65,126)]
    tmp_1.append(i * key[0] % key[1])

tmp_1 = bytes_to_long(bytes(tmp_1))

assert key[2] > 10000 and key[2] < 66000

ans = 1
for i in range(10):
    ans *= getPrime(32)

tmp_2 = pow(tmp_1, key[2], ans)

print("ans =", ans)
print("tmp_2 =", tmp_2)
# ans = 120796998476439420090152425236643185081062012915310701843783867909351022960528461757805572684277
# tmp_2 = 101439649710085699601183920154085425198153896186503375136461526208214527723176365783830083028733

首先对题目进行分析

file

这一部分就是对flag进行第一次加密操作

对flag的每一位进行乘以key[0]然后再模上key[1],将结果存放在tmp_1列表中

其中可以知道的是flag的每一位的ascii码都在65-126之间

然后根据提示可以知道flag的格式为:nynuctf{}

所以知道这个之后,就可以根据这几位来爆破出key[0]和key[1]

具体步骤如下:

1.假设现在已经得到tmp_1 = bytes_to_long(bytes(tmp_1))这一步操作之后的tmp_1,这个时候tmp_1是一个长数字

所以先进行类型转换,将它转为bytes类型

可以使用:long_to_bytes(secret)来操作,其中secret为加密的密文

2.然后现在需要循环遍历33-126(33-126为可打印字符,这个可以随意)来进行加密比对,当得到加密结果与我们转换之后的tmp_1相同的时候将数字打印出来即为key[0]和key[1]

3.代码如下:

tmp_1 = list(long_to_bytes(secret))
for i in range(33,126):
    for j in range(33,126):
        if(ord('n') * i % j == tmp_1[0]):
            if(ord('y') * i % j == tmp_1[1]):
                if(ord('n') * i % j == tmp_1[2]):
                    if(ord('u') * i % j == tmp_1[3]):
                        if(ord('c') * i % j == tmp_1[4]):
                            if(ord('t') * i % j == tmp_1[5]):
                                if(ord('f') * i % j == tmp_1[6]):
                                    print("key[0] =", i)
                                    print("key[1] =", j)

file

下面部分为rsa加密

其中循环生成n,然后将key[2]作为e,将第一步的加密结果作为明文进行加密,然后tmp_2为密文

对于n可以使用yafu进行分解

结果如下:

file

对于这类rsa计算方法和正常方法一样,只不过这里不知道e的值需要爆破一下

解rsa代码如下:

from Crypto.Util.number import *

a = [2907975361, 2651742167, 2330347433, 3479757329, 3277008277, 3941549713, 2780613821, 3275211067, 3974060789, 4132429661]
n = 1
phi = 1
for i in a:
    phi *= i-1
    n *= i

c = 101439649710085699601183920154085425198153896186503375136461526208214527723176365783830083028733

for e in range(10000,66000):
    d = inverse(e,phi)
    m = pow(c,d,n)
    tmp_1 = list(long_to_bytes(m))

但是第一步得到的密文转bytes之后不一定是可以显示字符串

所以需要将这两步进行结合爆破

代码如下:

from Crypto.Util.number import *

a = [2907975361, 2651742167, 2330347433, 3479757329, 3277008277, 3941549713, 2780613821, 3275211067, 3974060789, 4132429661]
n = 1
phi = 1
for i in a:
    phi *= i-1
    n *= i

c = 101439649710085699601183920154085425198153896186503375136461526208214527723176365783830083028733

for e in range(10000,66000):
    d = inverse(e,phi)
    secret = pow(c,d,n)
    tmp_1 = list(long_to_bytes(secret))
    for i in range(33,126):
        for j in range(33,126):
            if(ord('n') * i % j == tmp_1[0]):
                if(ord('y') * i % j == tmp_1[1]):
                    if(ord('n') * i % j == tmp_1[2]):
                        if(ord('u') * i % j == tmp_1[3]):
                            if(ord('c') * i % j == tmp_1[4]):
                                if(ord('t') * i % j == tmp_1[5]):
                                    if(ord('f') * i % j == tmp_1[6]):
                                        print("key[0] =", i)
                                        print("key[1] =", j)
                                        print("key[2] =", e)

然后经过一段时间的等待之后即可得到key

file

然后得到key[2]就可以计算出第一步加密的结果

from Crypto.Util.number import *

a = [2907975361, 2651742167, 2330347433, 3479757329, 3277008277, 3941549713, 2780613821, 3275211067, 3974060789, 4132429661]
n = 1
phi = 1
for i in a:
    phi *= i-1
    n *= i

c = 101439649710085699601183920154085425198153896186503375136461526208214527723176365783830083028733

e = 65533
d = inverse(e,phi)
m = pow(c,d,n)
tmp_1 = list(long_to_bytes(m))
print(tmp_1)
[50, 1, 50, 27, 9, 56, 12, 33, 85, 21, 35, 41, 67, 85, 1, 35, 9, 24, 1, 82, 56, 21, 65]

因为第一步加密几乎的不可逆的,所以需要再次爆破出flag

tmp_1 = [50, 1, 50, 27, 9, 56, 12, 33, 85, 21, 35, 41, 67, 85, 1, 35, 9, 24, 1, 82, 56, 21, 65]
for i in tmp_1:
    for j in range(65,126):
        if(j * 61 % 90 == i):
            print(chr(j), end="")

运行即可得到flag