国庆第二波-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
首先对题目进行分析
这一部分就是对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)
下面部分为rsa加密
其中循环生成n,然后将key[2]作为e,将第一步的加密结果作为明文进行加密,然后tmp_2为密文
对于n可以使用yafu进行分解
结果如下:
对于这类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
然后得到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