0x1 crypto
bvibvi
首先要通过验证问题,对一个等式计算求解,简单的枚举求解即可。
通过验证过后,需要回答一系列问题,是关于B站BV号和AV号的。
题目给出BV号,让我们找出对应的AV号。多组正确后再给AV号,让我们找出BV号。
简单的了解了下Bilibili的av号和bv号知识后,发现
av号对应url格式为 url =‘https://www.bilibili.com/video/av’+aid
bv号为 url =‘https://www.bilibili.com/video/’+bid
若手工一一查找太麻烦,另外程序也有时间限制,因此需要采取自动化办法获取av和bv对应关系。
可通过在网页源码查看对应的BV和AV,利用python re模块进行提取即可。
解题脚本
from pwn import *
import requests
r = remote('218.197.154.9' ,'16387')
context(log_level='debug')
print(string.printable)
def work():
r.recvuntil('Math:\n')
d1 =r.recvuntil(' *')[:-2]
r.recvuntil('+ ')
d2 = r.recvuntil(' ')
r.recvuntil('== ')
d3 = r.recvuntil(' ')
r.recvuntil('mod ')
d4 = r.recvuntil('\n')[:-1]
d1,d2,d3,d4 = int(d1),int(d2),int(d3),int(d4)
#print(int(d1),d2,d3,d4)
for x in range(d4):
if (d1*x+d2) % d4 == d3:
print(x)
r.sendlineafter('x :',str(x))
def bv():
i=5
while i:
i=i-1
aid = r.recvuntil('\n')[:-1]
url ='https://www.bilibili.com/video/av'+aid
q = requests.get(url)
res = re.findall(r'"videoData":{"bvid":"(.*)","aid":(.*),"videos"',q.text)
print(res[0][0])
r.sendline(res[0][0])
def av():
sleep(1)
i=15
while i:
i=i-1
bid = r.recvuntil('\n')[:-1]
url ='https://www.bilibili.com/video/'+bid
q = requests.get(url)
res = re.findall(r'"videoData":{"bvid":"(.*)","aid":(.*),"videos"',q.text)
#print(res[0][1])
r.sendline(res[0][1])
work()
r.recvuntil('id.\n')
bv()
r.recvuntil('number.\n')
av()
print(r.recvall())
notrsa
关于rsa的题目。
题目给了p q e c,但其中p不是素数,因此需要进一步对p分解,否则直接解密会出错。
借助yafu分解p
所有相当于RSA模数有三个素因子,利用欧拉定理得到
phi = (p1-1)*(p2-1)*(q-1)
于是可求出私钥d=invert(e,phi)
明文 flag = pow(c,d,p*q)
脚本
#!/usr/bin/env python
from Crypto.Util.number import *
import gmpy2
p = 0x501431403e46f960310474f59accb2cb
q = 0xb0b378d96238e799a2e544e7686f8d17
e = 0x10001
c = 0x9b941cce29810d1026e0005c1bd20f4234f7f210edd3ed369cdd3ff7b34c188
p1 = 10215054443853430669
p2 = 10420217054443542967
phi = (p1-1)*(p2-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,(p*q))
print(m)
print(long_to_bytes(m))
aes
cbc模式加密。加密方式如下
def aes_pad(s):
t = bytes((AES_KEYSIZE - len(s) % AES_KEYSIZE) * chr(AES_KEYSIZE - len(s) % AES_KEYSIZE),
encoding='utf-8')
return s + t
def enc():
f = open('plaintext', 'r')
plaintext = f.readlines()
f.close()
f = open('ciphertext', 'w')
for i in range(len(IV)):
aes = AES.new(key, AES.MODE_CBC, IV[i])
m = aes_pad(base64.b64decode(plaintext[i]))
cipher = aes.encrypt(m)
print(bytes.decode(base64.b64encode(cipher)), file=f)
f.close()
本题密钥已知,密文已知,但初始化IV未知。
AES算法的IV长度为16字节,暴力破解是不现实的。
cbc模式解密模式如下。在第二组密文解密时并不受到IV值影响,只需要有key和前一组密文即可。
所以可以获取到每行明文的第二个数块以及之后的数据块。
编写脚本尝试解密,看是否有发现
import string
def unpad(s):
t=0
#print((s[-1]))
return s[:-s[-1]]
def dec():
f = open('ciphertext', 'r')
cipher = f.readlines()
f.close()
f = open('plaintext1', 'w')
flag=''
for i in range(len(cipher)):
ci = (base64.b64decode(cipher[i]))
iv=b'\x00'*16 #iv可以任意
aes = AES.new(key, AES.MODE_CBC,iv)
#m = aes.decrypt(ci[16:]+ci[:16])
m = aes.decrypt(ci)
#print(m)
m=unpad(m)
#print(m,len(m))
flag+=chr(m[-1])
#print(base64.b64encode(m), file=f)
print(flag[::-1])
#print(''.join(flag))
f.close()
dec()
仔细观察解密后的数据,发现每行最后一个字节是明文,组合起来便是flag。出题人太会玩了。
需要注意解密后要进行unpad操作才能能得到原始m。
prism
这道题涉及到了RSA密码问题、离散对数密码问题。加密计算过程虽然复杂,但做题思路很清晰。
加密脚本
def enc(keys, m):
p, g, y = keys[-1]
while True:
k = getRandomInteger(2048)
if gmpy2.gcd(k, p-1) == 1:
break
c1 = pow(g, k, p)
m = (getRandomInteger(64) << m.bit_length()) + m
m = ((m << 64) + getRandomInteger(64))
c2 = pow(y, k, p) * m % p
return c1, c2
密钥来源
from Crypto.Util.number import getPrime, getRandomInteger, long_to_bytes, bytes_to_long
from Crypto.Cipher import AES
from Crypto.Util import Counter
import gmpy2
from secret import rsa_keygen
def FFF(food, key): #aesjiami
K = 0xe238c70fe2d1885a1b12debfa15484cab8af04675c39ff4c633d6177f234ed88
key = long_to_bytes(key, 32)
food = long_to_bytes(food, 128)
aes = AES.new(key, AES.MODE_CTR, counter=Counter.new(128, initial_value=K))
c = bytes_to_long(aes.encrypt(food))
return c
def GGG(food, key):
K = 0xfd94d8de73e4aa8f4f452782b98a7870e82ec92a9db606fe4ca41f32d6df90c5
K = long_to_bytes(K, 32)
food = long_to_bytes(food, 128)
aes = AES.new(K, AES.MODE_CTR, counter=Counter.new(128, initial_value=key))
c = bytes_to_long(aes.encrypt(food))
return c
def keygen():
keys = []
n0, e0 = rsa_keygen()
keys.append([n0, e0])
N0, E0 = n0, e0
while True:
p1 = getPrime(1024 // 2)
e1 = pow(p1, E0, N0)
q1 = getPrime(1024 // 2)
n1 = p1 * q1
phi1 = (p1-1)*(q1-1)
if e1 < n1 and gmpy2.gcd(e1, phi1) == 1:
break
keys.append([n1, e1])
N1, E1 = n1, e1
K2 = 0xb6a022cd2fb960d4b6caa601a0412918fd80656b76c782fa6fe9cf50ef205ffb
B2_1 = 8
B2_2 = 8
B2_3 = 1024
while True:
p2 = getPrime(2048 // 2)
i = 0
while True:
p2_1 = FFF(p2, K2 + i) #aes encrypt,i not known (0,8)
if p2_1 < N1:
break
i += 1
if i >= B2_1:
break
if i >= B2_1:
continue
p2_2 = pow(p2_1, E1, N1)
j = 0
while True:
p2_3 = GGG(p2_2, K2 + j)
x2 = (p2_3 << 1024) + getRandomInteger(1024)
q2 = gmpy2.next_prime(x2 // p2)
n2 = p2 * q2
if 0 <= (n2 >> 1024) - p2_3 < B2_3:
break
j += 1
if j >= B2_2:
break
if i <= B2_1 and j < B2_2:
break
e2 = 65537
keys.append([n2, e2])
N2, E2 = n2, e2
K3 = 0xfcec710a0313bb8f93e76e00ae6862b9be72dfd837db3b64ddde344bebfd2f50
B3_1 = 8
B3_2 = 1024
while True:
x3 = gmpy2.next_prime(getRandomInteger(2048) % N2)
if x3 >= N2:
continue
x3_2 = pow(x3, E2, N2)
i = 0
while True:
f3 = FFF(x3_2, K3 + i)
p3 = gmpy2.next_prime(f3)
if p3 > x3 and p3 - f3 < B3_2:
break
i += 1
if i >= B3_1:
break
if i < B3_1:
break
while True:
g3 = gmpy2.next_prime(getRandomInteger(p3.bit_length()) % p3)
if g3 < p3 and 1 == gmpy2.gcd(g3, p3-1):
break
y3 = pow(g3, x3, p3)
keys.append((p3, g3, y3))
P3, G3, Y3 = p3, g3, y3
B4 = 16384
while True:
x4 = gmpy2.next_prime(getRandomInteger(2048) % P3)
k = getPrime(2048)
if x4 >= P3 or gmpy2.gcd(k, P3-1) > 1:
continue
b4 = pow(Y3, k, P3) * x4 % P3
p4 = gmpy2.next_prime(b4)
g4 = pow(G3, k, P3)
if gmpy2.is_prime(p4) and x4 < p4 and g4