2024 年春秋杯网络安全联赛冬季赛

See anything in these pics?easy_flaskeasy_flask 是复现

Misc

See anything in these pics?

题目内容:
TBH THERE ARE SO MANY PICS NOT ONLY JUST 2 PIC
附件下载 提取码(GAME)备用下载

附件是一张 png 图片 Aztec.png 和一个加密的 zip 压缩包 YVL.zip

Aztec

根据图片特征以及它的名字可以知道这是 Aztec 条码,找个免费的在线扫码网站扫一下得到了 5FIVE

2

5FIVE 成功解开压缩包,得到一张 jpg 图片 YVL.png

YVL

把图片丢到随波逐流,发现藏了东西,foremost 提取出了一张黑色的 png 图片,再丢回随波逐流发现图片宽度和高度被修改过,可能存在隐写,恢复后得到图片

4

1
flag{opium_00pium}

简单算术

题目内容:想想异或附件下载 提取码(GAME)备用下载

附件的内容是 ys~xdg/m@]mjkz@vl@z~lf>b,根据提示可以知道要对明文进行简单的异或解密操作

1
2
3
4
5
cipher_text = "ys~xdg/m@]mjkz@vl@z~lf>b"
for key in range(256):
plain_text = ''.join([chr(ord(c) ^ key) for c in cipher_text])
if "flag" in plain_text:
print(plain_text)

写个脚本就能得到 flag 了

1
flag{x0r_Brute_is_easy!}

简单镜像提取

题目内容:
RR_studio
附件下载 提取码(GAME)备用下载

附件是 data.pcapng,丢到随波逐流就发现文件头不对了

接着用 foremost 提取出一个压缩包,解压得到 disk-recovery.img,再次丢到随波逐流就发现文件头不对

还是用 foremost 提取,这次发现提取出了一个 Excel 文档

5

1
flag{E7A10C15E26AA5750070EF756AAA1F7C}

压力大,写个脚本吧

题目内容:爆破附件下载 提取码(GAME)备用下载

附件是一个带密码的 zip 压缩包 zip_99.zip 和一个 txt 文档 password_99.txt,文档的内容是 RkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZH

先试了一下发现不是伪加密,然后直接拿文档的内容作为密码也失败了,接着我还试了下重复的片段 RkdGR0ZH 发现也不对

没试出来我就看了下里面的文档的 CRC 校验值竟然和外面这个是一样的

6

又联想到题目的 “爆破”,我就天真地以为是明文爆破,结果就是爆破了六个小时😡

7

后来才发现不对劲,把 RkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZHRkdGR0ZH 用 base64 解码的结果当作密钥试了下就解开了😭

解开了发现是层层嵌套的,并且每一层的压缩包的密码就是和压缩包放在一起那个 txt 文档里的内容用 base64 解码后的结果,写个脚本就搞定了(压缩包后面没用就先删掉了,txt 还有用就先留着不删)

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import zipfile
import os
import base64

# 设置初始参数
folder_path = r'E:\Downloads\zip_100' # 这里改成实际的地址

def get_password_from_txt(password_filename):
if not os.path.exists(password_filename):
print(f"警告: 密码文件 {password_filename} 不存在。")
return None

with open(password_filename, 'r') as file:
encoded_password = file.read().strip()

try:
# Base64解码
password = base64.b64decode(encoded_password).decode('utf-8')
return password
except Exception as e:
print(f"错误: 解码密码时出错 - {e}")
return None

def unzip_and_cleanup(zip_path, folder_path):
zip_filename = os.path.basename(zip_path)
password_num = zip_filename.split('.')[0].split('_')[1] # 提取数字部分如'99'
password_filename = os.path.join(folder_path, f"password_{password_num}.txt")

password = get_password_from_txt(password_filename)

if password is None:
return False

try:
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
# 尝试使用给定的密码解压
zip_ref.extractall(path=folder_path, pwd=password.encode())
print(f"成功解压: {zip_filename}")
return True
except RuntimeError as e:
print(f"解压失败: {zip_filename} - 错误信息: {e}")
return False

def process_nested_zips(folder_path, start_num):
current_num = start_num

while True:
zip_filename = f"zip_{current_num}.zip"
full_zip_path = os.path.join(folder_path, zip_filename)

# 检查文件是否存在
if not os.path.exists(full_zip_path):
print(f"文件 {zip_filename} 不存在,停止解压。")
break

if unzip_and_cleanup(full_zip_path, folder_path):
# 清理工作:删除原始ZIP文件和对应的TXT文件
password_filename = f"password_{current_num}.txt"
password_full_path = os.path.join(folder_path, password_filename)

# 删除文件
os.remove(full_zip_path)
# if os.path.exists(password_full_path):
# os.remove(password_full_path)

print(f"已删除: {zip_filename}{password_filename}")

# 继续处理下一个层级
next_zip_filename = f"zip_{current_num - 1}.zip"
next_full_zip_path = os.path.join(folder_path, next_zip_filename)
if os.path.exists(next_full_zip_path):
current_num -= 1
continue
else:
print("没有更多层级的压缩包了,解压完成。")
break
else:
print("解压过程中出现问题,停止进一步操作。")
break

# 解压缩
process_nested_zips(folder_path, 99)

解压到最后发现最后一层是 flag-hint.txt,内容是 PASSWORD+PASSWORD.png

根据最后一层的解压密码 89504E470D0A1A0A0000000D494844520000019000000190 不难看出这题是要把这些密码按顺序拼起来凑出一个 png 图片(png 的文件头是 89 50 4e 47 0d 0a 1a 0a

于是在上面代码的基础上加上下面的代码,把字符串拼起来拼凑出一张 png 图片

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
# 根据提示把密码文件解码得到的字符串拼接起来并传换成png图片
def concatenate_base64_decoded_from_txt_files(folder_path, start_num, end_num):
decoded_string = ''

for num in range(start_num, end_num + 1):
password_filename = os.path.join(folder_path, f"password_{num}.txt")

if not os.path.exists(password_filename):
print(f"警告: 密码文件 {password_filename} 不存在")
continue

with open(password_filename, 'r') as file:
encoded_password = file.read().strip()

try:
# Base64解码
decoded_data = base64.b64decode(encoded_password)
# 将解码后的二进制数据转换为字符串并拼接
decoded_string += decoded_data.decode(errors='replace')
except Exception as e:
print(f"错误: 解码 {password_filename} 时出错 - {e}")

return decoded_string

# 获取所有密码并解码为字符串
hex_string = concatenate_base64_decoded_from_txt_files(folder_path, 0, 99)

# 如果字符串以 'FG' 结尾,则移除 'FG'
while hex_string.endswith('FG'):
hex_string = hex_string[:-2]

# 将十六进制字符串转换为字节对象
try:
byte_data = bytes.fromhex(hex_string)
except ValueError as e:
print(f"Error converting hex to bytes: {e}")
exit(1)

# 指定输出文件名
output_filename = os.path.join(folder_path, "output_image.png")

# 写入二进制数据到文件
with open(output_filename, 'wb') as image_file:
image_file.write(byte_data)

完整代码如下

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import zipfile
import os
import base64

# 设置初始参数
folder_path = r'E:\Downloads\zip_100'

def get_password_from_txt(password_filename):
if not os.path.exists(password_filename):
print(f"警告: 密码文件 {password_filename} 不存在")
return None

with open(password_filename, 'r') as file:
encoded_password = file.read().strip()

try:
# Base64解码
password = base64.b64decode(encoded_password).decode('utf-8')
return password
except Exception as e:
print(f"错误: 解码密码时出错 - {e}")
return None

def unzip_and_cleanup(zip_path, folder_path):
zip_filename = os.path.basename(zip_path)
password_num = zip_filename.split('.')[0].split('_')[1] # 提取数字部分
password_filename = os.path.join(folder_path, f"password_{password_num}.txt")

password = get_password_from_txt(password_filename)

if password is None:
return False

try:
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
# 尝试使用给定的密码解压
zip_ref.extractall(path=folder_path, pwd=password.encode())
return True
except RuntimeError as e:
print(f"解压失败: {zip_filename} - 错误信息: {e}")
return False

def process_nested_zips(folder_path, start_num):
current_num = start_num

while True:
zip_filename = f"zip_{current_num}.zip"
full_zip_path = os.path.join(folder_path, zip_filename)

# 检查文件是否存在
if not os.path.exists(full_zip_path):
print(f"文件 {zip_filename} 不存在,停止解压")
break

if unzip_and_cleanup(full_zip_path, folder_path):
# 清理工作:删除原始ZIP文件和对应的TXT文件
password_filename = f"password_{current_num}.txt"
password_full_path = os.path.join(folder_path, password_filename)

# 删除文件
os.remove(full_zip_path)
# if os.path.exists(password_full_path):
# os.remove(password_full_path)

# 继续处理下一个层级
next_zip_filename = f"zip_{current_num - 1}.zip"
next_full_zip_path = os.path.join(folder_path, next_zip_filename)
if os.path.exists(next_full_zip_path):
current_num -= 1
continue
else:
break
else:
print("解压过程中出现问题,停止进一步操作")
break

# 解压缩
process_nested_zips(folder_path, 99)

# 根据提示把密码文件解码得到的字符串拼接起来并传换成png图片
def concatenate_base64_decoded_from_txt_files(folder_path, start_num, end_num):
decoded_string = ''

for num in range(start_num, end_num + 1):
password_filename = os.path.join(folder_path, f"password_{num}.txt")

if not os.path.exists(password_filename):
print(f"警告: 密码文件 {password_filename} 不存在")
continue

with open(password_filename, 'r') as file:
encoded_password = file.read().strip()

try:
# Base64解码
decoded_data = base64.b64decode(encoded_password)
# 将解码后的二进制数据转换为字符串并拼接
decoded_string += decoded_data.decode(errors='replace')
except Exception as e:
print(f"错误: 解码 {password_filename} 时出错 - {e}")

return decoded_string

# 获取所有密码并解码为字符串
hex_string = concatenate_base64_decoded_from_txt_files(folder_path, 0, 99)

# 如果字符串以 'FG' 结尾,则移除 'FG'
while hex_string.endswith('FG'):
hex_string = hex_string[:-2]

# 将十六进制字符串转换为字节对象
try:
byte_data = bytes.fromhex(hex_string)
except ValueError as e:
print(f"Error converting hex to bytes: {e}")
exit(1)

# 指定输出文件名
output_filename = os.path.join(folder_path, "output_image.png")

# 写入二进制数据到文件
with open(output_filename, 'wb') as image_file:
image_file.write(byte_data)

得到的图片是一张二维码,扫码就能得到 flag 了

8

1
flag{_PASSWORDs_is_fl@g!_}

Crypto

通往哈希的旅程

题目内容:在数字城,大家都是通过是通过数字电话进行的通信,常见是以 188 开头的 11 位纯血号码组成,亚历山大抵在一个特殊的地方截获一串特殊的字符串 "ca12fd8250972ec363a16593356abb1f3cf3a16d",通过查阅发现这个跟以前散落的国度有点相似,可能是去往哈希国度的。年轻程序员亚力山大抵对这个国度充满好奇,决定破译这个哈希值。在经过一段时间的摸索后,亚力山大抵凭借强大的编程实力成功破解,在输入对应字符串后瞬间被传送到一个奇幻的数据世界,同时亚力山大抵也开始了他的进修之路。(提交格式:flag {11 位号码})

根据题意,开头 3 位数 188 已经知道了,那就只需要尝试后面的 8 位数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import hashlib

# 给定的哈希值
target_hash = "ca12fd8250972ec363a16593356abb1f3cf3a16d"

# 尝试所有的11位数
for i in range(10**8): # 从0到99999999 (总共1亿个可能性)
phone_number = f"188{i:08d}" # 构建电话号码
hash_object = hashlib.sha1(phone_number.encode())
hex_dig = hash_object.hexdigest()

if hex_dig == target_hash:
print(f"Found match: {phone_number}") # Found match: 18876011645
break

1 分钟左右就试出来了

1
flag{18876011645}

你是小哈斯?

题目内容:年轻黑客小符参加 CTF 大赛,他发现这个小哈斯文件的内容存在高度规律性,并且文件名中有隐藏信息,他成功找到了隐藏的信息,并破解了挑战。得意地说:“成功在于探索与质疑,碰撞是发现真相的关键!”
附件下载 提取码(GAME)备用下载

题目内容如下

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
356a192b7913b04c54574d18c28d46e6395428ab
da4b9237bacccdf19c0760cab7aec4a8359010b0
77de68daecd823babbb58edb1c8e14d7106e83bb
1b6453892473a467d07372d45eb05abc2031647a
ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
c1dfd96eea8cc2b62785275bca38ac261256e278
902ba3cda1883801594b6e1b452790cc53948fda
fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
0ade7c2cf97f75d009975f4d720d1fa6c19f4897
b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
3bc15c8aae3e4124dd409035f32ea2fd6835efc9
21606782c65e44cac7afbb90977d8b6f82140e76
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
aff024fe4ab0fece4091de044c58c9ae4233383a
58e6b3a414a1e090dfc6029add0f3555ccba127f
4dc7c9ec434ed06502767136789763ec11d2c4b7
8efd86fb78a56a5145ed7739dcb00c78581c5375
95cb0bfd2977c761298d9624e4b4d4c72a39974a
51e69892ab49df85c6230ccc57f8e1d1606caccc
042dc4512fa3d391c5170cf3aa61e6a638f84342
7a81af3e591ac713f81ea1efe93dcf36157d8376
516b9783fca517eecbd1d064da2d165310b19759
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
d1854cae891ec7b29161ccaf79a24b00c274bdaa
7a81af3e591ac713f81ea1efe93dcf36157d8376
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
c2b7df6201fdd3362399091f0a29550df3505b6a
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
a0f1490a20d0211c997b44bc357e1972deab8ae3
3c363836cf4e16666669a25da280a1865c2d2874
4a0a19218e082a343a1b17e5333409af9d98f0f5
54fd1711209fb1c0781092374132c66e79e2241b
27d5482eebd075de44389774fce28c69f45c8a75
5c2dd944dde9e08881bef0894fe7b22a5c9c4b06
13fbd79c3d390e5d6585a21e11ff5ec1970cff0c
07c342be6e560e7f43842e2e21b774e61d85f047
395df8f7c51f007019cb30201c49e884b46b92fa
11f6ad8ec52a2984abaafd7c3b516503785c2072
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
7a38d8cbd20d9932ba948efaa364bb62651d5ad4
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
d1854cae891ec7b29161ccaf79a24b00c274bdaa
6b0d31c0d563223024da45691584643ac78c96e8
5c10b5b2cd673a0616d529aa5234b12ee7153808
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
54fd1711209fb1c0781092374132c66e79e2241b
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
6b0d31c0d563223024da45691584643ac78c96e8
58e6b3a414a1e090dfc6029add0f3555ccba127f
53a0acfad59379b3e050338bf9f23cfc172ee787
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
11f6ad8ec52a2984abaafd7c3b516503785c2072
95cb0bfd2977c761298d9624e4b4d4c72a39974a
395df8f7c51f007019cb30201c49e884b46b92fa
c2b7df6201fdd3362399091f0a29550df3505b6a
3a52ce780950d4d969792a2559cd519d7ee8c727
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
a0f1490a20d0211c997b44bc357e1972deab8ae3
3c363836cf4e16666669a25da280a1865c2d2874
4a0a19218e082a343a1b17e5333409af9d98f0f5
54fd1711209fb1c0781092374132c66e79e2241b
27d5482eebd075de44389774fce28c69f45c8a75
5c2dd944dde9e08881bef0894fe7b22a5c9c4b06
13fbd79c3d390e5d6585a21e11ff5ec1970cff0c
07c342be6e560e7f43842e2e21b774e61d85f047
395df8f7c51f007019cb30201c49e884b46b92fa
11f6ad8ec52a2984abaafd7c3b516503785c2072
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
7a38d8cbd20d9932ba948efaa364bb62651d5ad4
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
d1854cae891ec7b29161ccaf79a24b00c274bdaa
6b0d31c0d563223024da45691584643ac78c96e8
5c10b5b2cd673a0616d529aa5234b12ee7153808
3a52ce780950d4d969792a2559cd519d7ee8c727
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
aff024fe4ab0fece4091de044c58c9ae4233383a
58e6b3a414a1e090dfc6029add0f3555ccba127f
4dc7c9ec434ed06502767136789763ec11d2c4b7
8efd86fb78a56a5145ed7739dcb00c78581c5375
95cb0bfd2977c761298d9624e4b4d4c72a39974a
51e69892ab49df85c6230ccc57f8e1d1606caccc
042dc4512fa3d391c5170cf3aa61e6a638f84342
7a81af3e591ac713f81ea1efe93dcf36157d8376
516b9783fca517eecbd1d064da2d165310b19759
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
d1854cae891ec7b29161ccaf79a24b00c274bdaa
7a81af3e591ac713f81ea1efe93dcf36157d8376
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
c2b7df6201fdd3362399091f0a29550df3505b6a
356a192b7913b04c54574d18c28d46e6395428ab
da4b9237bacccdf19c0760cab7aec4a8359010b0
77de68daecd823babbb58edb1c8e14d7106e83bb
1b6453892473a467d07372d45eb05abc2031647a
ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
c1dfd96eea8cc2b62785275bca38ac261256e278
902ba3cda1883801594b6e1b452790cc53948fda
fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
0ade7c2cf97f75d009975f4d720d1fa6c19f4897
b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
3bc15c8aae3e4124dd409035f32ea2fd6835efc9
21606782c65e44cac7afbb90977d8b6f82140e76

看了下题目描述猜测这些是哈希值,搜了下 356a192b7913b04c54574d18c28d46e6395428ab 发现是 SHA-1,附上免费的转换网站

9

大胆猜测每一行就代表一个字符,flag 就藏在里面

然后针对常用的字符做一个彩虹表,查表拼接起来就好了(后来发现只用到了数字、小写字母和_{}

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# 哈希值列表
hashes_string = """356a192b7913b04c54574d18c28d46e6395428ab
da4b9237bacccdf19c0760cab7aec4a8359010b0
77de68daecd823babbb58edb1c8e14d7106e83bb
1b6453892473a467d07372d45eb05abc2031647a
ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
c1dfd96eea8cc2b62785275bca38ac261256e278
902ba3cda1883801594b6e1b452790cc53948fda
fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
0ade7c2cf97f75d009975f4d720d1fa6c19f4897
b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
3bc15c8aae3e4124dd409035f32ea2fd6835efc9
21606782c65e44cac7afbb90977d8b6f82140e76
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
aff024fe4ab0fece4091de044c58c9ae4233383a
58e6b3a414a1e090dfc6029add0f3555ccba127f
4dc7c9ec434ed06502767136789763ec11d2c4b7
8efd86fb78a56a5145ed7739dcb00c78581c5375
95cb0bfd2977c761298d9624e4b4d4c72a39974a
51e69892ab49df85c6230ccc57f8e1d1606caccc
042dc4512fa3d391c5170cf3aa61e6a638f84342
7a81af3e591ac713f81ea1efe93dcf36157d8376
516b9783fca517eecbd1d064da2d165310b19759
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
d1854cae891ec7b29161ccaf79a24b00c274bdaa
7a81af3e591ac713f81ea1efe93dcf36157d8376
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
c2b7df6201fdd3362399091f0a29550df3505b6a
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
a0f1490a20d0211c997b44bc357e1972deab8ae3
3c363836cf4e16666669a25da280a1865c2d2874
4a0a19218e082a343a1b17e5333409af9d98f0f5
54fd1711209fb1c0781092374132c66e79e2241b
27d5482eebd075de44389774fce28c69f45c8a75
5c2dd944dde9e08881bef0894fe7b22a5c9c4b06
13fbd79c3d390e5d6585a21e11ff5ec1970cff0c
07c342be6e560e7f43842e2e21b774e61d85f047
395df8f7c51f007019cb30201c49e884b46b92fa
11f6ad8ec52a2984abaafd7c3b516503785c2072
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
7a38d8cbd20d9932ba948efaa364bb62651d5ad4
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
d1854cae891ec7b29161ccaf79a24b00c274bdaa
6b0d31c0d563223024da45691584643ac78c96e8
5c10b5b2cd673a0616d529aa5234b12ee7153808
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
54fd1711209fb1c0781092374132c66e79e2241b
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
6b0d31c0d563223024da45691584643ac78c96e8
58e6b3a414a1e090dfc6029add0f3555ccba127f
53a0acfad59379b3e050338bf9f23cfc172ee787
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
11f6ad8ec52a2984abaafd7c3b516503785c2072
95cb0bfd2977c761298d9624e4b4d4c72a39974a
395df8f7c51f007019cb30201c49e884b46b92fa
c2b7df6201fdd3362399091f0a29550df3505b6a
3a52ce780950d4d969792a2559cd519d7ee8c727
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
a0f1490a20d0211c997b44bc357e1972deab8ae3
3c363836cf4e16666669a25da280a1865c2d2874
4a0a19218e082a343a1b17e5333409af9d98f0f5
54fd1711209fb1c0781092374132c66e79e2241b
27d5482eebd075de44389774fce28c69f45c8a75
5c2dd944dde9e08881bef0894fe7b22a5c9c4b06
13fbd79c3d390e5d6585a21e11ff5ec1970cff0c
07c342be6e560e7f43842e2e21b774e61d85f047
395df8f7c51f007019cb30201c49e884b46b92fa
11f6ad8ec52a2984abaafd7c3b516503785c2072
84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
7a38d8cbd20d9932ba948efaa364bb62651d5ad4
e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
d1854cae891ec7b29161ccaf79a24b00c274bdaa
6b0d31c0d563223024da45691584643ac78c96e8
5c10b5b2cd673a0616d529aa5234b12ee7153808
3a52ce780950d4d969792a2559cd519d7ee8c727
22ea1c649c82946aa6e479e1ffd321e4a318b1b0
aff024fe4ab0fece4091de044c58c9ae4233383a
58e6b3a414a1e090dfc6029add0f3555ccba127f
4dc7c9ec434ed06502767136789763ec11d2c4b7
8efd86fb78a56a5145ed7739dcb00c78581c5375
95cb0bfd2977c761298d9624e4b4d4c72a39974a
51e69892ab49df85c6230ccc57f8e1d1606caccc
042dc4512fa3d391c5170cf3aa61e6a638f84342
7a81af3e591ac713f81ea1efe93dcf36157d8376
516b9783fca517eecbd1d064da2d165310b19759
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
d1854cae891ec7b29161ccaf79a24b00c274bdaa
7a81af3e591ac713f81ea1efe93dcf36157d8376
53a0acfad59379b3e050338bf9f23cfc172ee787
042dc4512fa3d391c5170cf3aa61e6a638f84342
a0f1490a20d0211c997b44bc357e1972deab8ae3
53a0acfad59379b3e050338bf9f23cfc172ee787
4a0a19218e082a343a1b17e5333409af9d98f0f5
07c342be6e560e7f43842e2e21b774e61d85f047
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
54fd1711209fb1c0781092374132c66e79e2241b
c2b7df6201fdd3362399091f0a29550df3505b6a
356a192b7913b04c54574d18c28d46e6395428ab
da4b9237bacccdf19c0760cab7aec4a8359010b0
77de68daecd823babbb58edb1c8e14d7106e83bb
1b6453892473a467d07372d45eb05abc2031647a
ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
c1dfd96eea8cc2b62785275bca38ac261256e278
902ba3cda1883801594b6e1b452790cc53948fda
fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
0ade7c2cf97f75d009975f4d720d1fa6c19f4897
b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
3bc15c8aae3e4124dd409035f32ea2fd6835efc9
21606782c65e44cac7afbb90977d8b6f82140e76"""

import hashlib

# 定义字符集
charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-_=+[]{}\\|;:\'\",.<>/?'

# 创建字符到哈希值的映射
hash_to_char = {}
for char in charset:
# 计算每个字符的SHA-1哈希值
hash_object = hashlib.sha1(char.encode())
hex_dig = hash_object.hexdigest()
hash_to_char[hex_dig] = char

# 使用splitlines()方法将字符串按行分割成列表
provided_hashes = hashes_string.splitlines()

result = []
for hash_value in provided_hashes:
# 检查哈希值是否存在于映射中
if hash_value in hash_to_char:
result.append(hash_to_char[hash_value])
else:
result.append('⬛') # 不在映射中的哈希值用黑色方块占位

print("".join(result))

运行得到结果 1234567890-=qwertyuiopflag{no_is_flag}asdfghjklzxcvbnm,flag{game_cqb_isis_cxyz}.asdfghjklzxcvbnm,.qwertyuiopflag{no_is_flag}1234567890-=

1
flag{game_cqb_isis_cxyz}

Web

easy_flask

焚靖秒了

10

1
flag{48ad0cde8345c8b2608933ac4e85147e}