真的是让有些同学给我装到了
(狗头保命)vsCTF写到知识库里就没再管,今天看着他的博客,萌生写自己CSDN博客的想法。
Recovery
原题是这样的:
# I coded this so that I wouldn't have to use a database!
from random import randint
from base64 import b64encode
def validate(password: str) -> bool:
if len(password) != 49:
return False
key = ['vs'.join(str(randint(7, 9)) for _ in range(ord(i))) + 'vs' for i in password[::-2]]
gate = [118, 140, 231, 176, 205, 480, 308, 872, 702, 820, 1034, 1176, 1339, 1232, 1605, 1792, 782, 810, 1197, 880,
924, 1694, 2185, 2208, 2775]
if [randint(a, b[0]) for a, b in enumerate(zip(gate, key), 1) if len(b[1]) != 3 * (b[0] + 7 * a) // a]:#保障是个空列表
return False
#password = 'vsctf{ h 5 _ L G _ 3 3 i s d _ O _ h _ H L _ 1 3}'
hammer = {str(a): password[a] + password[a + len(password) // 2] for a in range(1, len(password) // 2, 2)}
block = b'c3MxLnRkMy57XzUuaE83LjVfOS5faDExLkxfMTMuR0gxNS5fTDE3LjNfMTkuMzEyMS5pMzIz'
if b64encode(b'.'.join([((b + a).encode()) for a, b in hammer.items()])) != block:
return False
return True
if __name__ == "__main__":
passwd = input('Please validate your ID using your password\n> ')
if validate(passwd):
print('Access Granted: You now have gained access to the View Source Flag Vault!')
else:
print('Access Denied :(')
一点点小思路:
条件if len(password) != 49: return False 可推知password 的长度为49
条件if b64encode(b’.'.join([((b + a).encode()) for a, b in hammer.items()])) == block return False
先将block的内容base64解码得到block_decode, 根据对应关系反向解出hammer,进而根据位置关系将password还原出偶数位
根据条件if [randint(a, b[0]) for a, b in enumerate(zip(gate, key), 1) if len(b[1]) != 3 * (b[0] + 7 * a) // a]:#保障是个空列表 return False 利用gate和长度关系还原奇数字母
解题脚本是这样的
from base64 import b64decode
password = [" " for _ in range(49)]
block = b'c3MxLnRkMy57XzUuaE83LjVfOS5faDExLkxfMTMuR0gxNS5fTDE3LjNfMTkuMzEyMS5pMzIz'
block_decode = b64decode(block).decode()
hammer = { int(i[2:]):i[0]+i[1] for i in block_decode.split('.')}
for i in hammer:
password[i] = hammer[i][0]
password[i+49//2] = hammer[i][1]
gate = [118, 140, 231, 176, 205, 480, 308, 872, 702, 820, 1034, 1176, 1339, 1232, 1605, 1792, 782, 810, 1197, 880, 924, 1694, 2185, 2208, 2775]
for i in range(0,len(gate)):
password[48-2*i] = (chr((gate[i] + 7 * (i+1)) // (i+1)))
print(''.join(password))
Baby RSA
原题是这样的:
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
from secret import e
with open("flag.txt",'r') as f:
flag = f.read().strip()
p = getPrime(128)
q = getPrime(128)
while p % e != 1:
p = getPrime(128)
while q % e != 1:
q = getPrime(128)
n = p * q
m = bytes_to_long(flag.encode())
c = pow(m, e, n)
print(f"Ciphertext: {hex(c)}")
with open("pubkey.pem",'w') as f:
pk = RSA.construct([n, e])
f.write(pk.exportKey('PEM').decode('utf-8'))
# Ciphertext: 0x459cc234f24a2fb115ff10e272130048d996f5b562964ee6138442a4429af847
e = 101
n = 52419317100235286358057114349639882093779997394202082664044401328860087685103
p = 184980129074643957218827272858529362113
q = 283378097758180413812138939650885549231
c = 0x459cc234f24a2fb115ff10e272130048d996f5b562964ee6138442a4429af847
可能会有些人问还有一个文件咋没放,之恶能说空间有限,把另一个文件读取出来写在第一个文件最后了。
一点点小思路:
题目的e,n,c是直接给出的,且n是相对较小的,可以通过分解获得p,q,但是存在以下关系
e ∣ ϕ ( n ) e | \phi(n) e∣ϕ(n)
使得不存在d,满足
e × d ≡ 1 ( m o d n ) e \times d \equiv 1 (\mod n) e×d≡1(modn)
只能是将方程
m e ≡ c ( m o d n ) m^e \equiv c (\mod n) me≡c(modn)
化为
m e ≡ m 1 e ≡ c ( m o d p ) m e ≡ m 2 e ≡ c ( m o d q ) m^e \equiv m_1^e \equiv c (\mod p) \newline m^e \equiv m_2^e \equiv c (\mod q) me≡m1e≡c(modp)me≡m2e≡c(modq)
利用sagemath在有限域上开n次方获得e个 m 1 m_1 m1 和e个 m 2 m_2 m2(不得不说sagemath是真的方便,完全不用自己写AMM算法,真的是棒极了),根据中国剩余定理可获得 e 2 e^2 e2 个m的值
m ≡ m 1 ( m o d p ) m ≡ m 2 ( m o d q ) m \equiv m_1 (\mod p ) \newline m\equiv m_2 (\mod q) m≡m1(modp)m≡m2(modq)
根据一定条件筛选即可获得明文
解题脚本来了
#sagemath脚本
# 一定要看好哦
from libnum import n2s
e = 101
n = 52419317100235286358057114349639882093779997394202082664044401328860087685103
p = 184980129074643957218827272858529362113
q = 283378097758180413812138939650885549231
c = 0x459cc234f24a2fb115ff10e272130048d996f5b562964ee6138442a4429af847
P.<m> = PolynomialRing(Zmod(p),implementation='NTL')
f = m^e - c;f
m1 = f.monic().roots()
P.<m> = PolynomialRing(Zmod(q),implementation='NTL')
f = m^e - c;f
m2 = f.monic().roots()
m1 = [int(i[0]) for i in m1]
m2 = [int(i[0]) for i in m2]
text_num = []
for i in m1:
for j in m2:
try:
text_num.append(crt([i,j],[p,q]))
except:
continue
for i in text_num:
txt = n2s(int(i))
if "vsctf" in str(txt):
print(txt)