第一届MineCraft CTF(WriteUp题解)

ChenFu 发布于 2025-10-29 63 次阅读


AI 摘要

《MineCraft CTF题解》揭秘:从勒索病毒溯源到逆向破解,攻击者IP、Webshell路径、病毒名称全曝光。内含SQL注入、摩斯密码、维吉尼亚等多类题型实战解析,附完整解题脚本与思路。

队伍名称: 你说我对不队

Misc方向

取证-1.1

1.请提交攻击者IP

Geek团队运营着一个大型的Minecraft多人服务器,拥有超过5000名注册玩家。2025年8月11日下午,服务器管理员收到多名玩家举报,称服务器出现异常行为,技术在排查后发现服务器文件被勒索组织投放了勒索病毒,导致文件被加密,技术将服务器内存镜像打包交给专业网络安全团队极安云科进行排查,请你协助公司方进行排查。

用户须知:本题涉及到真实环境勒索病毒,请在隔离环境下进行解题操作,严禁将本题所涉文件与外界互联网接触,下载附件则表示您已接受并承诺遵守该条约,若因违反本条约导致的病毒传播或文件被加密,本组委会不承担任何责任!

根据 lovelymem 工具网络信息中 可以发现攻击者IP 注意:内网IP

flag: MCCTF{10.10.0.1}

取证-2.1

请提交攻击者外联IP和端口

如上 也可以看出来

flag: MCCTF{66.240.205.34:9002}

取证-3.1

请提交该服务器皮肤上传系统中发现的webshell绝对路径(含文件名)

可以在lovelymem NTFS文件时间线上搜索.php后缀 然后发现有shell.php 然后去加载镜像中

可以发现也找到了shell.php 但是是被感染过的文件 提交flag不能带 被感染的后缀

同时也可以发现这属于C盘

flag格式:MCCTF{D:/xxx/xxx.php}

flag: MCCTF{C:/phpstudy_pro/WWW/uploads/shell.php}

取证-4.1

请提提交该服务器勒索病毒名称

flag格式:MCCTF{WannaCry 1.0}

这边也是在文件夹中发现了 LB3Decryptor.exe

LB3 = LockBit 3.0

LockBit 勒索病毒,其 3.0 版本通常被简称为 LB3。

这个病毒会加密文件并留下 [字符].README.txtLB3Decryptor.exe 在文件夹中也是发现这两个文件

flag: MCCTF{LockBit 3.0}

取证-5.1

请提提交该勒索组织留下的浏览器地址的顶级域名,如:.com

flag格式:MCCTF{.com}

根据是勒索病毒 肯定不会那么明显和暴露 然后我就搜了一波 顶级域名

通常在网络安全事件中,勒索组织会使用 .onion 域名(Tor 隐藏服务的顶级域名)来隐藏其服务器地址。

同时去lovelymem 正则搜索了下 正好核验到的 查到了

所以顶级域名为 .onion

Flag: MCCTF{.onion}

ezmisc-签到

另外,放提示说

签到提示

王梓芷唱过

所以我可以猜到是一路生花

所以flag:MCCTF{Wellcome_To_1th_MCCTF_一路生花}

Web方向

ez_Minecraft_login

我只知道大概率考的是sql注入,但是没想到会这么简单。

万能密码搞定

登录进去之后F12看源码

flag:mcctf{security_Big_Panda}

MinecraftWeb

答题即可:1.25,67,-13 2.3 3.0 4.c 5.8

flag:mcctf{M1n3cr4ft_R3d5t0n3_Ch4ll3ng3_5ucc3ss}

Re方向

Ezhard_launcher

简单的python逆向(这道题真的算re吗)

def show_flag():
    p1 = [0x66,0x6c,0x61,0x67,0x7b]
    p2 = [0x68,0x34,0x72,0x64,0x5f,0x6c,0x61,0x75,0x6e,0x63,0x68,0x33,0x72,0x5f]
    p3 = [0x72,0x33,0x76,0x5f,0x63,0x74,0x66,0x7d]
    flag = ''.join([chr(x^0) for x in p1+p2+p3])
messagebox.showinfo('flag', flag)

直接把flag展示出来了,做题的时候直接print就行

flag:flag{h4rd_launch3r_r3v_ctf}

Crypto方向

Ezlog

这么大文本量只能交给ai分析

注意到有个这个可能是某个编码之后的flag

flag:mcctf{ez!_Steve111}

咩咩咩

虽然但是这道题只是一个从摩斯密码包装起来的题目

然后就可以解出来密文是

FOAMRVNGUKFQQUU

之后见到有密钥的题目,第一时间想到的就是维基尼亚

于是

flag:mccctf{yangzofzgxzyjmn}

ez_lattice

首先我们知道flag被分成了10部分,每部分转字节后分别加密表示。

以下是加密过程

n是一个1024位的素数。

k是一个320位的素数。

然后他把flag分成了十份分别进行加密

$$ h_i \equiv k \cdot flag_i^{-1} \pmod{n} $$

$$flag_i \cdot h_i \equiv k \pmod{n} \quad (\forall i \in [0,9])$$

所以我们可以进行解密

首先我们不妨设第一块儿flag是mcctf{

于是我们可以通过这个来解出k,因为

$$k \equiv f_0 \cdot h_0 \pmod{n}$$

有了k我们就可以往下解密其他部分的flag,因为

$$\forall i \in [0,10),都有f_i \equiv k \cdot h_i^{-1} \pmod{n}$$

所以我们可以有如下exp:

from Crypto.Util.number import long_to_bytes, bytes_to_long
from sage.all import *

n = 101058037881577920580002375991533361443161573598172872401436929130908010655347634552777064174546568575027746607488492099154312267724394462943506690144947830040343315369562513570527692894685015573081207528621819747699733304080614793374057284273387848357708739112531677281801323793173090364390370736467003582917
h = [65238694465386915975309840141683615649716012162296959248563569592374718661731701206400896806537952397410032261877378530686978759625292099657084619983375773255755144153781457417211674091516407534881571548771997217431814162001948536903510439216595988996202297986689400937900640116301788349788192250828531102128, 32068430839487144716294122362877372185693231094331598085462142396101367356886620469702732239532304931830205469549873073426114974524345753699104479003686428551918989837919692818874041699167857438504796702427222322750641837975840611428682636854000155270647980139296254355022602725831316373502464385756822509507, 48045538813319220884490922546018868575029946351799253696566675045038593914426407040185597260237676046539039366729571890778376978523204708113947916683959718708951574554301326506033685253589648114421528029323355988178699924863264060114597711724540199556277259170518549061045104668001222710528847166168767224549, 75123995948950968391603159591624639368414690146643442871589447787252191810497231696845253418339980365162413355185111520483921331823652266243697559776174240013810488917495610598469082493126712875223200656678886780170706766832861117452830161713449328056483280254149803408052080851148204725932967126493489495389, 42343824812526091206264281076069981510653655573870037741842182418474719039360760283698683250943728878536765635239317776400805788012233353293622608102030711446811052604409325460820893599261928948443614050545507085890105202716250838690843035633052646253790841787346488131868389877735682981371140434336342163669, 37628269352817676029356094741613805749594096808670358767615556155530757612666502454541938594622721603313749449559343049177509738095358796943332112708078541782706675648358891508089680020008921913219362413211208103447607363315907316039312691994345309495981824477958094292712571053294153865686883217285045072976, 73095252261793287281307332092278639250704283375416144614680921495193800381044097746018933097918509033128787939821334122567907138901258104948978871755972801343922472074421943147663482695952043375035475082008819785709339730299175470843123204596279944349658280821397882576553260815905563725407952447607089415633, 8361412049519617647068414326705006074844850312921172001754491320379019244806566558657382200324831784028297924464089518976736942901670220750313172374617027089856976338617784260689863433040095122712749142220670740521573738642943802961154307094774904173422138158314888817191233893356292405644600013350124816088, 62352524946552767010792198212753557220884107271554779577796506420796971189249469475111704305722210605467500390830564039781429821148651682920442985923243637249469873109032519540399258091710648539664160224041270628257896923843424376128648420038693104506093124335294407330397776591999820661062819804224881373090, 45213281711383478082421649210599256239528608897580799695344082282030442480159495245224471785682835728050988008519768665616995327124516724160052452164034157361068252085880379351444661551341271829125924017634986473455126215443151677035338594360564464453084451500811436155828884254112395862897223575590665873227]

# 假设flag的开头是'mcctf{',计算第一个分块的可能值
# flag是b'mcctf{...}',分成10部分,每部分长度为len_flag // 10
# 我们需要计算第一个分块的值
flag_start = b'mcctf{'
# 计算第一个分块的值
# 由于flag被分成10部分,每部分的长度是len_flag // 10
# 但len_flag是动态的,取决于UUID的长度
# UUID的标准长度是36字符(包括'-'),所以flag的总长度是6 + 36 + 1 = 43
len_flag = 43
part_len = len_flag // 10  # 4
# 第一个分块是_flag[0:4] = b'mcct'
f0 = bytes_to_long(b'mcct')
# 计算k
k = (h[0] * f0) % n
# 验证k是否对其他h_i也成立
for i in range(1, 10):
    fi = (k * inverse_mod(h[i], n)) % n
    print(long_to_bytes(fi))
# 发现输出不全是合理的flag部分,因此可能需要调整part_len或f0

# 另一种方法是利用h_i * f_i ≡ h_j * f_j ≡ k (mod n)
# 因此 h_i * f_i ≡ h_j * f_j (mod n)
# 可以表示为 f_i ≡ f_j * h_j * h_i^{-1} (mod n)
# 由于flag的格式已知,可以尝试用已知的部分恢复其他部分

# 另一种思路是注意到k是h_i * f_i % n,且k是相同的
# 因此可以计算k的候选值
# 从h[0]和h[1]的关系:
# h[0] * f0 ≡ h[1] * f1 (mod n)
# f1 ≡ f0 * h[0] * h[1]^{-1} (mod n)
# 由于f0和f1是连续的flag部分,可以尝试用f0的候选值计算f1

# 假设f0是b'mcct',计算f1
f0 = bytes_to_long(b'mcct')
f1 = (f0 * h[0] * inverse_mod(h[1], n)) % n
print(long_to_bytes(f1))  # 输出可能是b'f{...'的一部分

# 继续拼接flag
flag_parts = []
for i in range(10):
    fi = (k * inverse_mod(h[i], n)) % n
    flag_parts.append(long_to_bytes(fi))
    print(f"Part {i}: {long_to_bytes(fi)}")

# 拼接所有部分
flag = b''.join(flag_parts)
print(flag)
# 可能需要调整part_len或f0的初始值

# 由于flag的总长度是43,分成10部分,每部分长度为4或5
# 尝试part_len = 5
len_flag = 43
part_len = (len_flag + 9) // 10  # 5
# 第一个分块是_flag[0:5] = b'mcctf'
f0 = bytes_to_long(b'mcctf')
k = (h[0] * f0) % n
flag_parts = []
for i in range(10):
    fi = (k * inverse_mod(h[i], n)) % n
    flag_parts.append(long_to_bytes(fi))
    print(f"Part {i}: {long_to_bytes(fi)}")
flag = b''.join(flag_parts)
print(flag)
# 输出可能是完整的flag

# 可能需要截断到正确的长度
flag = flag[:43]
print(flag)

运行得到flag:mcctf{f670d7a5-80db-4b7a-86f3-466a0e1e7daf}

此作者没有提供个人介绍。
最后更新于 2026-03-11