writeup for 2021 巅峰极客 Crypto

啊好久没更新blog了, 打了下巅峰极客, 写一下wp吧.

MedicalImage

一个图片加密脚本, 函数f(x)被隐藏了, 但给了提示, 是logistic map, (在b站看下视频, 数学真的好神奇啊).而且参数是最大合法值, 也就是, 那么函数f(x)

然后就是对着加密流程写解密了…. 没有啥特别的 逆着加密过程写解密就行, p0,c0就那几个值爆破就行, 一开始随便拿101,201试了下…直接对了

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from decimal import *
from PIL import Image
import numpy as np
from time import time
getcontext().prec = 20


R = Decimal(4)
r1 = Decimal('0.478706063089473894123')
r2 = Decimal('0.613494245341234672318')
r3 = Decimal('0.946365754637812381837')
const = 10 ** 14
im = Image.open(
r'flag_enc.bmp'
)
size = im.size
w,h = size
im = np.array(im)



def f(x):
return Decimal(4 * x * (1 - x))

for i in range(200):
r1 = f(r1)
r2 = f(r2)
r3 = f(r3)

S = time()
p0 = 101
c0 = 201
for x in range(w):
for y in range(h):
k = int(round(const*r3))%256
k = bin(k)[2:].ljust(8,'0')
k = int(k[p0%8:]+k[:p0%8],2)
r3 = f(r3)
m0 = ((k ^ im[y,x] ^ c0 ) - k) % 256
c0 = im[y,x]
p0 = m0
im[y,x] = m0
arr = []
for x in range(w):
for y in range(h):
x1 = int(round(const*r1))%w
y1 = int(round(const*r2))%h
arr += [(x,y,x1,y1)]
r1 = f(r1)
r2 = f(r2)
for z in arr[::-1]:
x,y,x1,y1 = z
tmp = im[y,x]
im[y,x] = im[y1,x1]
im[y1,x1] = tmp
m = Image.new('P', size,'white')
pixels = m.load()
for i in range(m.size[0]):
for j in range(m.size[1]):
pixels[i,j] = (int(im[j][i]))
m.save(r'flag.bmp')
print(time()-S)

LearnSM4

果然是learnSM4, 看了题目马上跑去学SM4了, 看了一下加密过程, 不难

看题目, 要求利用给出的加密过程中的leak得到轮密钥的第一个,也就是key[0]

来看看第一轮加密的过程

这个就是我们要求的, 是两个变换合在一起的, 自己手动试了一下, 发现变换时可以用z3梭出来的, 直接就能逆出来

而上面的等式中是自己构造的, 能利用题目给的leak得到, 传r=0,i=0~3即可

这里我直接传, 可以有

这几天写远程的脚本写吐了, 真不想写, 手打了这题, exp只有一步一步的 都是本地跑出结果手动输入上去的, 讲究着看吧(懒)

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
def getnum(arr):
HEX = ''
for i in arr:
HEX += hex(i)[2:]
return int(HEX,16)

# 用z3逆T变换中的r(x)
def f(B):
B1 = (((B << 2 ) & 0b1100000000000000000000000000000000) >>32) ^ (B << 2) & 0xffffffff
B2 = (((B << 10) & 0b111111111100000000000000000000000000000000) >> 32) ^ (B<<10) & 0xffffffff
B3 = (((B << 18) & 0b11111111111111111100000000000000000000000000000000) >> 32) ^ (B<<18) & 0xffffffff
B4 = (((B << 24) & 0b11111111111111111111111100000000000000000000000000000000) >> 32) ^ (B<<24) & 0xffffffff
return B ^ B1 ^ B2 ^ B3 ^ B4

S = z3.Solver()
x = z3.BitVec('x',64)
S.add((getnum([161,203,79,94])^1)- f(x)==0)
if S.check():
print(S.model())

# 逆S(x)
def findS(value):
for i in range(256):
if S_BOX[i] == value:
return i

print(hex(2217051833)[2:]) # 2217051833 z3梭出的结果
# 0x842586b9

key = '0'
arr = [0x84,0x25,0x86,0xb9]
for i in arr:
key += hex(findS(i))[2:]
print(int(key,16))

把最后得到的key值发过去就好了, 这里都没用到给的hint, 也不知道是不是非预期

crtrsa

有一种已知dp求p的方法 可以直接爆破dp然后求出p

这博客写的越来越懒了哈哈 有什么不清楚的qq找我吧 3519728596

这样也挺好 记录一下自己做过的就好了… 我是fw