KCTF2022-签到题-险象环生

KCTF2022-签到题-险象环生

https://ctf.pediy.com/game-season_fight-204.htm

1
2
3
4
公开的用户及序列号:

用户名 : 461D7AD538F179EE
序列号 : 40403286341212

序列号长度必须为14(0xE)。

序列号分两部分,前10位根据用户名计算,后4位为代码解密的密钥。

后4位已知,计算出前10位即可,程序中按位进行比较,下断点吐出序列号即可。

image-20220510160249116

GIF

image-20220510162025288

错误的解密密钥会导致程序执行异常(指令异常)。

image-20220510161102810

1
2
3
4
5
ZHIGHEST
32509419591212

KCTF
15920863481212

这个题目有bug,用户名为zhighest时无解,因为密钥会出现NULL字符,无法直接输入。

1
2
zhighest
133622859 \x00 1212

代码解密前后对比:

image-20220510165424563

如果没有公开的用户名与序列号如何求解?

已知输入的密钥只会影响每4个字节中的2个字节(DWORD的低位),统计解密前每组数据中高位的值,一般X86的字节码中00,FF较多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
dic = {}

data = open('before.hex', 'rb').read()
data_arr = bytearray(data)
data_len = len(data)
for i in range(data_len//4):
a = data_arr[0+i*4]
b = data_arr[1+i*4]
key = '%.2X%.2X'%(b,a) # 此处同时统计低2位,也可分开统计
try:
dic[key] += 1
except:
dic[key] = 1

dic_sorted =sorted(dic.items(),key=lambda x:x[1], reverse=False)
for i in dic_sorted:
print(i)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# output
...
('7039', 1)
('6E43', 1)
('7031', 1)
('D5AC', 1)
('817B', 1)
('FA40', 1)
('8137', 2)
('4031', 2)
('5543', 2)
('F8F4', 2)
('9137', 2)
('8F43', 2)
('446D', 2)
('1143', 2)
('04FC', 2)
('8FBC', 2)
('F8D0', 3)
('FB40', 8)
('04BC', 8)
('FB43', 9)

其中0xFB400x04BC0xFB43出现频率较高,分别将他们与0x0000, 0xFFFF异或,则密钥可能的值为:

1
2
0xFB40, 0x04BC, 0xFB43
0x04BF, 0xFB43, 0x04BC

还需要满足十进制长度为4,范围进一步缩小

1
2
3
4
5
0x04BF -> 1215
0x04BC -> 1212

0xFB40 -> 64320
0xFB43 -> 64323