CryptoCTF easy
文章目录
- 2023
- suction
- Blue Office
- 2022
- Baphomet
2023
suction
题目描述:
from Crypto.Util.number import *
from flag import flagdef keygen(nbit, r):while True:p, q = [getPrime(nbit) for _ in '__']e, n = getPrime(16), p * qphi = (p - 1) * (q - 1)if GCD(e, phi) == 1:N = bin(n)[2:-r]E = bin(e)[2:-r]PKEY = N + Epkey = (n, e)return PKEY, pkeydef encrypt(msg, pkey, r):m = bytes_to_long(msg)n, e = pkeyc = pow(m, e, n)C = bin(c)[2:-r]return Cr, nbit = 8, 128
PKEY, pkey = keygen(nbit, r)
print(f'PKEY = {int(PKEY, 2)}')
FLAG = flag.lstrip(b'CCTF{').rstrip(b'}')
enc = encrypt(FLAG, pkey, r)
print(f'enc = {int(enc, 2)}')
题目分析:
给出了n,e,c且每个都是少最后8bit
n - 256bit,e - 16bit,由于都比较小,可直接爆破出来
n这里用factor()分解,若最后分解得到的是两个数,并且都是128bit,那么p,q,n都可以确定了
n出来了那之后再爆e和c,256 * 256,也不大,最后通过得到的flag是否都为可打印字符来判断flag是否正确
from Crypto.Util.number import *
from gmpy2 import *
PKEY = 55208723145458976481271800608918815438075571763947979755496510859604544396672
ENC = 127194641882350916936065994389482700479720132804140137082316257506737630761 << 8
n_ = int(bin(PKEY)[2:-8],2) << 8
e_ = int(bin(PKEY)[-8:],2) << 8# for i in range(45,256):
# print(i)
# n = n_ + i
# if n % 2 == 0:
# continue
# a = factor(n)
# if len(a) == 2:
# print(n,a,i) # 69n = 55208723145458976481271800608918815438075571763947979755496510859604544396613
p = 188473222069998143349386719941755726311
q = 292926085409388790329114797826820624883
phi = (p - 1) * (q - 1)
for i in range(256):e = e_ + iif not isPrime(e):continuefor j in range(256):c = ENC + jd = inverse(e,phi)m = pow(c,d,n)flag = long_to_bytes(int(m))if flag.isascii():print(flag)
# CCTF{6oRYGy&Dc$G2ZS}
Blue Office
题目描述:
import binascii
from secret import seed, flagdef gen_seed(s):i, j, k = 0, len(s), 0while i < j:k = k + ord(s[i])i += 1i = 0while i < j:if (i % 2) != 0:k = k - (ord(s[i]) * (j - i + 1))else:k = k + (ord(s[i]) * (j - i + 1))k = k % 2147483647i += 1k = (k * j) % 2147483647return kdef reseed(s):return s * 214013 + 2531011def encrypt(s, msg):assert s <= 2 ** 32c, d = 0, senc, l = b'', len(msg)while c < l:d = reseed(d)enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')c += 1return encenc = encrypt(seed, flag)
print(f'enc = {binascii.hexlify(enc)}')
题目分析:
gen_seed()压根没用到呀,感觉是用来耗时间的,有些人喜欢顺着看下来,看完之后才发现这串没用,但时间也过去了。所以还是从加密那里看起吧。
步入正题
主要在下面两串
d = reseed(d)
enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
第一串LCG
,第二串flag的其中一个字节和d的第16-24位(1个字节)异或。assert s <= 2 ** 32
表明s应该在32位左右,但我们只需用到24位,所以可以把这个运算看成GF(2 ** 24)
下的运算,flag的格式固定CCTF{}
,故通过异或运算可以得到seed的第16-24位,还16位未知,不大直接爆破,之后flag也就出来了
import binascii
enc = 'b0cb631639f8a5ab20ff7385926383f89a71bbc4ed2d57142e05f39d434fce'
enc = binascii.unhexlify(enc)
flag = b'CCTF{'def reseed(s):return s * 214013 + 2531011def encrypt(s, msg):assert s <= 2 ** 32c, d = 0, senc, l = b'', len(msg)while c < l:d = reseed(d)enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')c += 1return encs1 = (enc[0] ^ flag[0]) << 16for i in range(2 ** 16):seed = s1 + iflag = encrypt(seed,enc[1:])if b'CTF' in flag:print(flag)
# CCTF{__B4ck_0r!F1c3__C1pHeR_!!}
2022
Baphomet
题目描述:
from base64 import b64encode
from flag import flagdef encrypt(msg):ba = b64encode(msg.encode('utf-8'))baph, key = '', ''for b in ba.decode('utf-8'):if b.islower():baph += b.upper()key += '0'else:baph += b.lower()key += '1'baph = baph.encode('utf-8')key = int(key, 2).to_bytes(len(key) // 8, 'big')enc = b''for i in range(len(baph)):enc += (baph[i] ^ key[i % len(key)]).to_bytes(1, 'big')return encenc = encrypt(flag)
f = open('flag.enc', 'wb')
f.write(enc)
f.close()
题目分析:
密文长度为48,说明key
长度为6(字节)
又CCTF{
有40bit
,大于6 * 6
(base64
以6字节分组加密)
故可知baph
前6位q0nurN
,与密文前6位异或得到key
key
和密文都知道,异或便可得到完整flag
未完待续…