Preface

Crypto出题质量挺差的…其他方向全程看队友输出(8说了线下撤硕见

you raise me up

$mod\ 2^{512}$的DLP,按位恢复即可(赛后看其他师傅基本都是用的sage的discrete_log,扒了下源码发现这个内置函数用的PH算法,而这题的阶又足够光滑,所以也能秒出)

1
2
3
4
5
6
7
8
9
10
11
12
13
n = 2
phi = 1
flag = [0, 1]
for i in range(2, 513):
n *= 2
phi *= 2
candidate = []
for i in flag:
if pow(m, i, n) == c % n:
candidate.append(i)
flag = [x + phi for x in candidate] + candidate
for i in flag:
print(long_to_bytes(i))

easy_ya

先靶机交互proof_of_work拿数据(没提示明文串长度,但是一猜4就中了- -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from hashlib import *
from pwn import *
import string
import itertools

#context.log_level = "debug"

io = remote("39.96.90.217", "17497")
io.recvuntil("= ")
suffix = io.recvline().strip().decode("utf-8")
print(suffix)
io.recvuntil("openssl_")
mode = io.recvuntil(">")[:-1].decode("utf-8")
print(mode)
pts = itertools.product(string.printable, repeat=4)
len = 100**4
cnt = 0
for pt in pts:
if cnt % 1000 == 0:
print("{}%".format(100*cnt/len))
p = "".join(list(pt))
if mode == "sha1":
ct = sha1(p.encode()).hexdigest()
elif mode == "sha224":
ct = sha224(p.encode()).hexdigest()
elif mode == "sha256":
ct = sha256(p.encode()).hexdigest()
elif mode == "sha384":
ct = sha384(p.encode()).hexdigest()
elif mode == "sha512":
ct = sha512(p.encode()).hexdigest()
elif mode == "md5":
ct = md5(p.encode()).hexdigest()
else:
exit(0)
if ct[:20] == suffix:
print(p)
break
cnt += 1
io.interactive()

然后GCD分解RSA模数,进而拿到Key

1
[136, 145, 137, 128, 136, 177, 151, 160, 191, 167, 129, 153, 178, 129, 149, 191, 174, 137]

拿到Key以后,又知每个分组加密后的密文

1
hint = nhex((y << 52) ^ (pads << 20) ^ z)

则有 y = hint >> 52

high_pads = (cipher % (2**52)) >> 32 << 12

low_z = cipher % (2**20)

中间未知的12比特直接爆破即可,又有 (32 * pad) % 0x100000000 == pads

即pad高5位未知,同样爆破即可,编写脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from tqdm import tqdm
from Crypto.Util.number import *

limit = lambda n: n & 0xffffffff

def decode(cipher):
flags = []
a = 2291239296
b = 2293340064
c = 3215425945
d = 2994836927
high_pads = (cipher % (2**52)) >> 32 << 12
mid = (cipher % (2**32)) >> 20
low_z = cipher % (2**20)
for i in tqdm(range(2**12)):
for j in range(2**5):
pads = high_pads + i
# (32 * pad) % 0x100000000 == pads
low_pad = pads >> 5
y = cipher >> 52
z = ((i ^ mid) << 20) + low_z
pad = (j << 27) + low_pad
for k in range(32):
z = limit(z - ((y*16 + c) ^ (y + pads) ^ ((y>>5) + d)))
y = limit(y - ((z*16 + a) ^ (z + pads) ^ ((z>>5) + b)))
pads = limit(pads - pad)
if pads != 0:
continue
flag = long_to_bytes(y) + long_to_bytes(z)
mark = True
for _ in flag:
if 0 < _ < 32 or _ >= 128:
mark = False
break
if mark == True:
flags.append(flag)
return flags

flag1 = decode(0xa5c5825052a4f2f97d50d)
flag2 = decode(0x916584dbfa561434b59a9)
flag3 = decode(0xd4148395b3a564bc85ef5)
flag4 = decode(0xb165eb6c68948a4860b12)
flag5 = decode(0xe698497f90f8b6fa51e0a)

半分钟出结果

boom

md5在线查库 + 三元一次方程 + 一元二次方程(绝了