2025 RCTF - Misc - WriteUp
碎碎念
很不错的一次竞赛体验,最终咱SU取得了第五名的好名次,虽然有点可惜没有拿到前三(甚至夺冠),但也不赖,下次分站赛继续努力qwq
这次Misc题的难度还是偏中等的,在48小时的鏖战中,顺利解决了90%的题目,差一道dc bot实在是超纲了不太会,区块链也是最后熬夜拷打ai整出来的,也是十分不易,希望下次能有更好的表现吧~
Speak Softly Love
知识点省流
Web取证
WP
网络取证题
第一问
根据视频的信息,直接在youtube里搜关键词快速定位到了这个视频,答案为8ssDGBTssUI

第二问
视频介绍里,提到了这个项目的网站

进网站可以看到有对应的项目仓库,装个svn的gui工具

访问仓库,可以看到有若干版本

在v0.9里找到soft error相关的记录,发现revision是178,所以答案是r178(gpt告诉我的格式)

第三问
在网站里可以快速定位到作者的个人官网https://mateusz.viste.fr/
在最下面可以找到

答案是https://mateusz.viste.fr/mateusz.ogg
第四问
个人主页里提到了有一个gopher空间,访问进去可以找到捐赠链接

或者直接搜关键词也能看到


Wanna Feel Love
知识点省流
Web取证
WP
网络取证题
第一问
题目给了个附件 里面是有eml邮件
看了一下邮件内容,一眼垃圾邮件隐写 解隐写拿到

第二问
邮件里有个xm文件 ai分析一波发现要用OpenMPT打开,下个工具
说是要提取feel的信息,切到feel的波形发现明显是转01,黑为0红为1


写脚本提取
import soundfile as sf
import numpy as np
VOLUME_THRESHOLD = 0.3 # 判断音量高低的阈值
def rms_volume(segment):
"""计算该音频片段的 RMS 平均音量"""
return np.sqrt(np.mean(segment ** 2))
def extract_volume_bits(path):
audio, sr = sf.read(path)
# 多声道 -> 单声道
if audio.ndim > 1:
audio = audio.mean(axis=1)
segment_samples = int(0.050 * sr) # 50ms
bits = []
for i in range(0, len(audio), segment_samples):
segment = audio[i:i + segment_samples]
if len(segment) < segment_samples:
break
vol = rms_volume(segment)
bit = 1 if vol >= VOLUME_THRESHOLD else 0
bits.append(str(bit))
return "".join(bits)
if __name__ == "__main__":
path = "Feel.flac"
bitstring = extract_volume_bits(path)
print(bitstring)
得到答案I Feel Fantastic heyheyhey
第三问 通过搜索第二问的答案可以找到这个猎奇小玩意

然后可以gpt梭哈

第四问
继续gpt梭哈,页面也可以自己搜到,不难

同时通过调查可以发现一篇关键文章 https://yitzilitt.medium.com/the-story-behind-i-feel-fantastic-tara-the-singing-android-and-john-bergeron-fc83de9e8f36 里面有我们想要的所有内容
第五问
在关键文章的评论里可以找到
答案为https://www.findagrave.com/memorial/63520325/john-louis-bergeron

Shadows of Asgard
知识点省流
webshell流量分析
WP
流量分析题
第一问
跟踪第一个http流就看到了

第二问
往后分析,发现这里传了aeskey和iv还有data,说明是aes加密了数据 并且key一直没变

ai搞了个脚本来解密
import base64
import json
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
# === 填入你的数据 ===
aesKey_b64 = "WzUsMTM5LDI0NSwyMjAsMjMxLDQ2LDIzNCwxNDYsMjQ4LDIxMSwyLDIxMywyLDE2NSw5OCwxMTgsMTAzLDE2MiwzLDE1MCw0LDUzLDE3OSwxOTQsODQsMjA3LDQ1LDI0NSw4OCwxNzksMTkzLDEwMV0="
aesIV_b64 = "WzEyNCwyMzIsMjU0LDE5LDI1MCw0OSw1MCw4MywyMjksMjQ0LDI4LDIyMiw4MywzMywyMDIsNl0="
data_hex = "6781ed63ff3d0c5a8960573c821f293cf3f59d678671645d40a72c9ed3bbccd29ad40f754ef11b77b033f8338888a30080f7dfb242241bf1fae6e4cd903e3c257457846ece5bb9c190ee9fc367f728daadabfabf929e75c7db7e111a32919c0e"
# === decode key/iv ===
aesKey = bytes(json.loads(base64.b64decode(aesKey_b64)))
aesIV = bytes(json.loads(base64.b64decode(aesIV_b64)))
ciphertext = bytes.fromhex(data_hex)
def try_aes_cbc(key, iv, ct):
try:
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = cipher.decrypt(ct)
# CBC 需要去 padding
return unpad(pt, AES.block_size).decode('utf-8', errors='replace')
except Exception:
return None
def try_aes_ctr(key, iv, ct):
try:
# CTR 的 iv 是 nonce
cipher = AES.new(key, AES.MODE_CTR, nonce=iv)
pt = cipher.decrypt(ct)
return pt.decode('utf-8', errors='replace')
except Exception:
return None
# === 尝试解密 ===
print("=== 尝试 AES-256-CBC ===")
cbc_res = try_aes_cbc(aesKey, aesIV, ciphertext)
print(cbc_res if cbc_res else "CBC 解密失败")
print("\n=== 尝试 AES-256-CTR ===")
ctr_res = try_aes_ctr(aesKey, aesIV, ciphertext)
print(ctr_res if ctr_res else "CTR 解密失败")
解出路径

第三问
一样的解数据,根据描述藏了隐写,同一个流里发现png图片内有base数据

提出来解密就行,得到id

第四问
找数据然后解密

第五问
接着解数据


Asgard Fallen Down
补充说明
由于本人实在懒得再做了 遂这里直接用队友 Sep 的WP)『 已获 Sep 批准,感谢 』
知识点省流
Webshell流量分析 Pro
WP
流量分析题
Challenge 1: The First Command
干扰的流量太多,不太好找
在流207中发现类似连接成功的流量

解码看看,看到了熟悉的进程

同时我们注意到,响应包中有三个奇怪的base64字符串

解码看一下,发现第一个长度是32,第二个是16,猜测为AES的key和iv


继续往后看,在之后紧跟着的包中看到,一串神秘的base64

使用之前得到的密钥和iv可以成功解密

得到命令spawn whoami
然后在之后的

得到命令执行结果

Challenge 2: The Heartbeat
很明显之前的命令执行过程含有心跳包机制,在207流中很明显看到时间间隔是10s

Challenge 3: The Heart of Iron
继续解密即可


找到响应包解密


得到答案Intel64 Family 6 Model 191 Stepping 2, GenuineIntel
Challenge 4: Odin's Eye
搜索关键词build:20251115可在2787流中找到本题的执行命令


发现之后有很多大块的响应包,猜测是可能图片base64后太大一次不好传输于是分段传输
正则匹配,解密

不知道为啥cbc没解出来,cbcnopadding出了
解密result

得到图片,工具是TscanPlus

The Alchemist's Cage
知识点省流
提示注入
WP
ez提示注入题
进去先输个soul 创建个对象
然后就可以开始在五轮内进行注入攻击了,很简单的,随便让它爆爆就出来了,这里是让它重复上一轮回复,当出现指定关键词(这里是谎言),输出关键字符串

vault
知识点省流
不懂 反正区块链我不喜欢
WP
丢给ai分析大概知道是要用sui环境去编译然后运行程序跟靶机进行交互
去下个预编译好的程序,然后就可以跑了
关键在代码
但是不懂区块链只能让ai帮忙做,换了两轮ai,gpt和gemini都怪怪的,最后用claude梭出来了
改了客户端的vault.move 然后修改Move.toml和Solve.move拿到了flag


https://claude.ai/share/87c74de4-00d5-4ac9-bfce-a8faecb24525


module solution::solution { use sui::coin::{Self, TreasuryCap}; use sui::tx_context::TxContext; use challenge::vault::{Self, Vault, AirdropTracker}; use challenge::vault_coin::VAULT_COIN; public fun solve( vault: &mut Vault, tracker: &mut AirdropTracker, treasury: &mut TreasuryCap<VAULT_COIN>, ctx: &mut TxContext ) { vault::request_airdrop(tracker, treasury, ctx); let proof_coin = coin::mint(treasury, 100_000_000_000, ctx); vault::buy_flag(tracker, vault, proof_coin, ctx); } }
