碎碎念
第一次参加这个赛,因为一些原因,组好队了才知道只有web misc 和crypto方向的题,队伍里只有我一个对得上的,最后只能独自奋战了。不过比较好的是红明谷的题目难度还可以,不算难。misc这边全都是脚本题,有对应思路搞个脚本就做出来了(甚至直接gpt) 最后拿了个44名,还不错,下次数字中国积分赛争取能跟队友们冲个决赛qwq
异常行为溯源
知识点省流
本题考查流量取证
WP
用tshark把data.data导出,然后写脚本解码,最后统计哪个ip最多
tshark导出(有很多奇怪的协议导不出来,但其实不影响)
1tshark -r network_traffic.pcapng -T fields -e data.data > data.txt用脚本处理数据
1import base64
2import json
3
4def hex_to_ascii(file_path, output_path):
5 try:
6 with open(file_path, 'r', encoding='utf-8') as infile, open(output_path, 'w', encoding='utf-8') as outfile:
7 for line in infile:
8 line = line.strip() # 去除换行符和空格
9 try:
10 ascii_text = bytes.fromhex(line).decode('ascii') # hex解码
11 base64_decoded_text = base64.b64decode(ascii_text).decode('utf-8') # Base64 解码
12 json_data = json.loads(base64_decoded_text) # 解析JSON数据
13 if 'msg' in json_data:
14 base64_encoded_msg = json_data['msg'] # 提取msg字段
15 final_decoded_msg = base64.b64decode(base64_encoded_msg).decode('utf-8') # 再次Base64解码
16 outfile.write(final_decoded_msg + '\n')
17 except (ValueError, base64.binascii.Error, UnicodeDecodeError, json.JSONDecodeError):
18 print(f"无法解码的行: {line}")
19 except FileNotFoundError:
20 print("文件未找到,请检查路径是否正确!")
21
22# 示例用法
23input_file = "data.txt" # 你的hex编码数据文件
24output_file = "decoded_output.txt" # 解码后的输出文件
25hex_to_ascii(input_file, output_file)
26print("解码完成,结果已保存到", output_file)导入linux,统计ip出现次数,最多那个就是flag
1cat decoded_output.txt | awk '{print$1}' | sort | uniq -c | sort -nr | more数据校验
知识点省流
本题考查写脚本
WP

要保证每一条都是合规,要注意ip也得检验(要符合xxx.xxx.xxx.xxx,xxx不能大于255)
1import csv
2import hashlib
3import re
4import ecdsa
5import base64
6import os
7
8
9def md5_hash(value):
10 return hashlib.md5(value.encode('utf-8')).hexdigest()
11
12
13def verify_signature(serial_number, username, signature):
14 try:
15 # Ensure the public key file exists based on the serial_number
16 public_key_file = os.path.join('ecdsa-key', f"{serial_number}.pem")
17
18 if not os.path.isfile(public_key_file):
19 raise FileNotFoundError(f"公钥文件未找到: {public_key_file}")
20
21 # Read the public key from the file
22 with open(public_key_file, 'r') as key_file:
23 public_key = key_file.read()
24
25 verifier = ecdsa.VerifyingKey.from_pem(public_key)
26 signature_bytes = base64.b64decode(signature)
27 verifier.verify(signature_bytes, username.encode('utf-8'))
28 return True
29 except (ecdsa.BadSignatureError, ValueError, FileNotFoundError) as e:
30 print(f"验证签名失败: {e}")
31 return False
32
33
34def validate_row(index, row):
35 errors = []
36
37 # 校验 UserName 格式
38 if not re.fullmatch(r'User-\w+', row[1]):
39 errors.append("UserName 格式错误")
40
41 # 校验 UserName_Check
42 if row[2] != md5_hash(row[1]):
43 errors.append("UserName_Check 错误")
44
45 # 校验 Password 格式
46 if not re.fullmatch(r'[A-Za-z0-9]+', row[3]):
47 errors.append("Password 格式错误")
48
49 # 校验 Password_Check
50 if row[4] != md5_hash(row[3]):
51 errors.append("Password_Check 错误")
52
53 # 校验 Signature
54 if not verify_signature(row[0],row[1], row[6]): # Use Serial_Number for public key lookup
55 errors.append("Signature 校验失败")
56
57 # 校验 IP 格式
58 ip = row[5]
59 ip_pattern = r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
60 if not re.match(ip_pattern, ip):
61 errors.append("IP 格式错误")
62
63 if errors:
64 print(f"第 {index + 1} 行数据不合规: {', '.join(errors)}")
65
66
67def read_csv(file_path):
68 with open(file_path, mode='r', encoding='utf-8') as file:
69 reader = csv.reader(file)
70 headers = next(reader) # 读取并跳过表头
71
72 for index, row in enumerate(reader):
73 validate_row(index, row)
74
75
76# 示例调用
77csv_file_path = "data.csv" # 请将此路径更改为你的 CSV 文件路径
78read_csv(csv_file_path)Strange_Database
知识点省流
本题考查脚本小子,rc4加密,rsa加密 pem私钥解密
WP
500个db文件里的数据都进行了RSA加密,要写脚本解出来
同时每个pem文件都用openssl加密过,也要逐一解密
看了一下key里面的私钥,都是加密过的,数量太多只能用脚本解了
1#!/usr/bin/env python3
2import glob
3import os
4from cryptography.hazmat.primitives import serialization
5from cryptography.hazmat.backends import default_backend
6
7
8def decrypt_pem_file(filename):
9 # 读取加密的 PEM 文件
10 with open(filename, "rb") as f:
11 encrypted_key = f.read()
12
13 # 从文件名中提取密码:取最后一个 '-' 后面的部分,去除扩展名
14 base_name = os.path.basename(filename)
15 password_with_ext = base_name.split('-')[-1]
16 password = password_with_ext.rsplit('.', 1)[0]
17
18 try:
19 # 加载并解密 PEM 文件,password 需要为字节串
20 private_key = serialization.load_pem_private_key(
21 encrypted_key,
22 password=password.encode(),
23 backend=default_backend()
24 )
25 except Exception as e:
26 print(f"文件 {filename} 解密失败:{e}")
27 return None
28
29 # 将解密后的私钥转换为不加密的 PEM 格式
30 try:
31 decrypted_key = private_key.private_bytes(
32 encoding=serialization.Encoding.PEM,
33 format=serialization.PrivateFormat.TraditionalOpenSSL,
34 encryption_algorithm=serialization.NoEncryption()
35 )
36 except Exception as e:
37 print(f"序列化私钥时出错 {filename}: {e}")
38 return None
39
40 return decrypted_key
41
42
43def batch_decrypt():
44 output_dir = "decrypted"
45 if not os.path.exists(output_dir):
46 os.makedirs(output_dir)
47
48 # 遍历当前目录下所有符合 OAEP-*.pem 格式的文件
49 pem_files = glob.glob("key/OAEP-*.pem")
50 if not pem_files:
51 print("未找到符合格式的 PEM 文件。")
52 return
53
54 counter = 0 # Initialize the counter
55
56 for pem_file in pem_files:
57 print(f"正在解密文件 {pem_file} ...")
58 decrypted_key = decrypt_pem_file(pem_file)
59 if decrypted_key:
60 output_file = os.path.join(output_dir, f"OAEP-{counter}.pem") # Use the counter for the output file name
61 with open(output_file, "wb") as f:
62 f.write(decrypted_key)
63 print(f"文件 {pem_file} 解密成功,输出文件为 {output_file}\n")
64 counter += 1 # Increment the counter for the next file
65 else:
66 print(f"文件 {pem_file} 解密失败。\n")
67
68
69if __name__ == "__main__":
70 batch_decrypt()解完再读取db文件再去解密db里的数据
1import glob
2import os
3import sqlite3
4from time import sleep
5
6from Crypto.PublicKey import RSA
7from Crypto.Cipher import PKCS1_OAEP
8import base64
9
10
11def read_db_data(db_file):
12 # 连接到 SQLite 数据库
13 conn = sqlite3.connect(db_file)
14
15 # 创建一个游标对象,用于执行 SQL 查询
16 cursor = conn.cursor()
17
18 try:
19 # 执行查询,获取所有表的名字
20 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
21 tables = cursor.fetchall()
22
23 if tables:
24 table_name = tables[0][0] # 假设我们选择第一个表
25
26 # 执行查询,读取表中的数据
27 cursor.execute(f"SELECT * FROM {table_name};")
28 rows = cursor.fetchall()
29
30 decoded_data = [] # 用于存储所有解码的数据
31 # 假设数据在第四列(索引为3)
32 for row in rows:
33 # 将解码后的数据加入列表
34 decoded_data.append(base64.b64decode(row[0]))
35 # print(decoded_data)
36 return decoded_data # 返回所有解码后的数据
37
38 except sqlite3.Error as e:
39 print(f"Error reading the database: {e}")
40 finally:
41 # 关闭连接
42 conn.close()
43
44
45def rsa_decrypt(private_key_path, ciphertext):
46 # 从文件读取私钥
47 with open(private_key_path, 'rb') as f:
48 private_key_pem = f.read()
49
50 private_key = RSA.import_key(private_key_pem)
51 cipher = PKCS1_OAEP.new(private_key)
52
53 # 解密
54 decrypted_data = cipher.decrypt(ciphertext)
55 return decrypted_data.decode()
56
57
58def process_db_and_pem_files(db_directory, pem_directory, output_file):
59 """处理所有的DB和PEM文件并将解密结果保存到一个txt文件中"""
60 with open(output_file, 'wb') as out_file:
61 for i in range(500):
62 # DB文件路径
63 db_file_path = os.path.join(db_directory, f'database-{i}.db')
64
65 # 查找匹配的PEM文件,格式为 'OAEP-i-xxxxxx-decrypted'
66 pem_file_pattern = os.path.join(pem_directory, f'OAEP-{i}-*.pem')
67 pem_files = glob.glob(pem_file_pattern)
68
69 if not pem_files:
70 print(f"没有找到匹配的PEM文件: {pem_file_pattern}")
71 continue
72
73 # 选择找到的第一个PEM文件
74 pem_file_path = pem_files[0]
75
76 # 确保DB文件和PEM文件都存在
77 if not os.path.exists(db_file_path) or not os.path.exists(pem_file_path):
78 print(f"文件不存在: {db_file_path} 或 {pem_file_path}")
79 continue
80
81 # 读取DB文件的加密数据
82 encrypted_data = read_db_data(db_file_path)
83
84 # 解密数据
85 try:
86 for t in range(20):
87 decrypted_data = rsa_decrypt(pem_file_path, encrypted_data[t])
88 # print(decrypted_data)
89 # 将解密后的数据追加到输出文件
90 out_file.write(decrypted_data.encode()) # 将字符串转换为字节写入文件
91 out_file.write(b'\n') # 可以加一个换行符分隔每个文件的内容
92
93
94 except Exception as e:
95 print(f"解密文件 {db_file_path} 时发生错误: {e}")
96
97
98if __name__ == '__main__':
99 db_directory = 'database' # DB文件所在的目录
100 pem_directory = 'decrypted' # PEM文件所在的目录
101 output_file = 'output/decrypted_data3.txt' # 总的解密结果保存文件
102
103 process_db_and_pem_files(db_directory, pem_directory, output_file)将其中一db文件用在线db查看网站查看一下可以看到有如下字段

解密完所有数据后导出Type一列,再简单处理一下会发现里面有Enc和Key两个比较特别的用户,不难看出一个对应密文一个对应密钥

猜测是某种带Key的加密,分别将他们其对应行号的Remark值拼接,最后用RC4解密即可

Comments will be available soon.