题目描述:
from Crypto.Util.number import *
from flag import flag
def keygen(nbit, r):
while True:
p, q = [getPrime(nbit) for _ in '__']
e, n = getPrime(16), p * q
phi = (p - 1) * (q - 1)
if GCD(e, phi) == 1:
N = bin(n)[2:-r]
E = bin(e)[2:-r]
PKEY = N + E
pkey = (n, e)
return PKEY, pkey
def encrypt(msg, pkey, r):
m = bytes_to_long(msg)
n, e = pkey
c = pow(m, e, n)
C = bin(c)[2:-r]
return C
r, 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) # 69
n = 55208723145458976481271800608918815438075571763947979755496510859604544396613
p = 188473222069998143349386719941755726311
q = 292926085409388790329114797826820624883
phi = (p - 1) * (q - 1)
for i in range(256):
e = e_ + i
if not isPrime(e):
continue
for j in range(256):
c = ENC + j
d = inverse(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(int(m))
if flag.isascii():
print(flag)
# CCTF{6oRYGy&Dc$G2ZS}
题目描述:
import binascii
from secret import seed, flag
def gen_seed(s):
i, j, k = 0, len(s), 0
while i < j:
k = k + ord(s[i])
i += 1
i = 0
while 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 % 2147483647
i += 1
k = (k * j) % 2147483647
return k
def reseed(s):
return s * 214013 + 2531011
def encrypt(s, msg):
assert s <= 2 ** 32
c, d = 0, s
enc, l = b'', len(msg)
while c < l:
d = reseed(d)
enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
c += 1
return enc
enc = 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 + 2531011
def encrypt(s, msg):
assert s <= 2 ** 32
c, d = 0, s
enc, l = b'', len(msg)
while c < l:
d = reseed(d)
enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
c += 1
return enc
s1 = (enc[0] ^ flag[0]) << 16
for i in range(2 ** 16):
seed = s1 + i
flag = encrypt(seed,enc[1:])
if b'CTF' in flag:
print(flag)
# CCTF{__B4ck_0r!F1c3__C1pHeR_!!}
题目描述:
from base64 import b64encode
from flag import flag
def 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 enc
enc = 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
未完待续…