ISCC 的部分 Mobile+Misc WP,练武区域赛+总决赛。misc 过于逆天,尤其是神经网络和八卦 😅 也是赤完了

部分附件下载链接(提取码 iscc):百度网盘

Stage 1: ISCC2025 Stage1 WP

Mobile

邦布出击

下载附件,有一个 apk 和一个 sqlite 数据库,数据库无法直接打开,被加密了。

首先 jadx 反编译 apk,分析代码可知,flag 内容为对(a, "WhItenet", getiv())DES 加密

其中getiv()MainActivity类下的一个 native 层函数,可以直接 hook 调用
a类调用了b.b()方法得到一段 Blowfish 加密字符串,key 未知
20250729154908-2025-07-29-15-49-09

dH类可找到几段 base64,解密较长的两段可得到提示三次加密及一个假 flag。随后将三段短的字符串拼接,连续解 3 次 base64,可以得到一个 key

尝试用这个 key 打开加密数据库,成功
20250729155154-2025-07-29-15-51-54

在数据库内可以得到一个新的 key:CdEfGhIjKlMnOpQr
20250729155210-2025-07-29-15-52-11

下面的 unicode 提示 key 是真的,而 flag 是假的。结合前面分析的代码,推测这个 key 就是 Blowfish 加密使用的 key,编写 js 脚本利用 frida 对com.example.mobile01下的bDESHelperDESHelper进行 hook,修改b.c的返回为得到的 key

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
function hook() {
Java.perform(function () {
let b = Java.use("com.example.mobile01.b");
b["c"].implementation = function () {
return "CdEfGhIjKlMnOpQr";
};
let DESHelper = Java.use("com.example.mobile01.DESHelper");
DESHelper["encrypt"].implementation = function (str, str2, str3) {
console.log(
`DESHelper.encrypt is called: str=${str}, str2=${str2}, str3=${str3}`
);
let result = this["encrypt"](str, str2, str3);
console.log(`DESHelper.encrypt result=${result}`);
return result;
};
Java.choose("com.example.mobile01.MainActivity", {
onMatch: function (instance) {
instance.Jformat("ISCC{114514}");
},
onComplete: function () {},
});
});
}

setImmediate(hook);

终端运行frida –U mobile01 –l payload.js
20250729155419-2025-07-29-15-54-19

得到 flagISCC{uuz5/S6X/LDAs8E7cbSOjposlYylNeHn}

Misc

返校之路

下载附件,解压后得到两个压缩包,第一个压缩包part1.zip为伪加密,使用随波逐流工具一键修复后解压得到readme.txt

1
2
3
4
5
一转眼,寒假已经过去,同学们都怀着怎样的心情踏上返校之路呢?

你是一名学生,从刚下高铁,准备乘坐19站地铁返回学校。短短的假期总是让人留恋,而返校的路似乎格外漫长。

在途中,你发现了一个神秘的压缩包,以及一张写着bfs???的纸条,这似乎隐藏着一些重要的信息。。。

使用bfs???作为掩码,利用 ARCHPR 工具爆破得到密码bfsYfx,解压压缩包,得到三张图片,两张是地铁站站台图片,一张是北京城市轨道交通线网图

picture2.pnglsb 提取 RGB 数据,可找到字符串flag_is_MNVUM2KXIRUFQU2VN46Q====

先解 base32 再解 base64 得rAbX8WIJ

题目中提到“19 站地铁”,从第一张图片3 号线朝阳站4 号线魏公村站途经 19 站的地铁路线为 3->10->4,将3104拼接到rAbX8WIJ后得到 flag

1
ISCC{rAbX8WIJ3104}

取证分析

下载题目给的两个附件,一个为 vmem 镜像,一个为 word 文档

将文档改后缀为 zip 并解包,在[Content_Types].xml内可以找到注释<!-- nawbcuzcdzbd -->

使用 R-Studio 扫描镜像,在原始文件-归档内可找到一个 zip 文件,直接恢复,需要密码才能解压

使用 ARCHPR 工具爆破压缩包,得到密码bfs775,解压后得到三个文本文件

Alphabet.txt

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

hint.txt

1
rxms{ husqzqdq oubtqd }

readme.txt

1
一段奇奇怪怪的字符

对 hint 里的字符串凯撒解密得到flag{ vigenere cipher },提示维吉尼亚密码

Alphabet.txt内提及了杨辉三角,并且给了 10 个数对,推测是利用这些数对从杨辉三角中提取数字生成 key

推测数对对应的是杨辉三角中的行与列,由于杨辉三角第nn行只有nn个数,且第nnmm列的数为(n1m1)\binom{n-1}{m-1},所以后一个数字为行数而前一个数字为列数,编写脚本取出这些数字,并把它们映射为模 26 意义下的大写字母 A-Z

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from math import comb

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

def decrypt(col, row):
v = comb(row - 1, col - 1)
m = v % 26 # 余 0 对应 Z,其余 1–25 则对应 A–Y
print(f"第{row}行第{col}列:", v, "对应", chr((m - 1) % 26 + ord("A")))
return chr((m - 1) % 26 + ord("A"))

plaintext = "".join(decrypt(c, r) for c, r in pairs)
print("Key: ", plaintext)

解密得到 key 为IICCNJAYER,作为维吉尼亚密码的 key 解密nawbcuzcdzbd得到 flag

1
ISCC{fsuzplzezitv}

签个到吧

下载附件并解压,得到一张 jpg 图片flag_is_not_here.jpg和一个 zip 压缩包,压缩包无法直接解压,用随波逐流查看可以发现是文件头被修改,010 改504b0304或直接用随波逐流修复即可解压,得到一张 png 图片0001_5.png
20250729155746-2025-07-29-15-57-46

第二张图片根据资料可推断为猫脸变换(Arnold 变换)

20250729155807-2025-07-29-15-58-08

推测需要利用两张图片异或,编写脚本

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
import cv2
import numpy as np
from PIL import Image
def arnold_decode(image, shuffle_times, a, b):
decode_image = np.zeros(shape=image.shape, dtype=np.uint8)
h, w = image.shape[0], image.shape[1]
N = h
for _ in range(shuffle_times):
tmp_image = np.zeros_like(decode_image)
for x in range(h):
for y in range(w):
new_x = ((a * b + 1) * x - b * y) % N
new_y = (-a * x + y) % N
tmp_image[new_x, new_y, :] = image[x, y, :]
decode_image = tmp_image
cv2.imwrite('0001_5.png', decode_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
return decode_image
def xor_images(image_path_1, image_path_2, output_path):
img1 = Image.open(image_path_1).convert('RGB').rotate(90, expand=True)
img2 = Image.open(image_path_2).convert('RGB')
if img1.size != img2.size:
raise ValueError(f"图片尺寸不一致: img1={img1.size}, img2={img2.size}")
img1_data = np.array(img1)
img2_data = np.array(img2)
xor_data = np.bitwise_xor(img1_data, img2_data)
xor_image = Image.fromarray(xor_data)
xor_image.save(output_path)
print(f"异或结果已保存至: {output_path}")
if __name__ == "__main__":
input_image = cv2.imread('0001_5.png')
decoded_image = arnold_decode(input_image, shuffle_times=1, a=1, b=-2)
cv2.imwrite('decoded_0001_5.png', decoded_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
xor_images("decoded_0001_5.png", "flag_is_not_here.jpg", "result.png")

运行后得到图片
20250729155932-2025-07-29-15-59-32

支付宝扫码得到 flag

1
ISCC{n7uRGAuTTy7i}

睡美人

下载附件,得到一个压缩包,解压后为一张图片。使用 binwalk 提取得到一个加密的压缩包,需要密码

由题目中提示“红红红红红红绿绿绿蓝”的“色彩秘方”可以推测是从 RGB 数据中按一定方式提取值,编写脚本还原压缩包密码

具体方式为sumR*0.6+sumG*0.3+sumB*0.1,即遍历所有像素得到的 RGB 值按6:3:1比例运算得到一个浮点数1375729349.6

利用该浮点数解压压缩包得到一段 wav 音频
20250729160422-2025-07-29-16-04-22

在提示后藏了一段曼彻斯特编码,解码后就能获取 flag

后期重找的脚本

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
import scipy.io.wavfile as wavfile
import numpy as np

def load_audio_file(filename):
try:
sample_rate, data = wavfile.read(filename)
return sample_rate, data
except Exception as e:
print(f"ERROR : {e}")
return None, None

def preprocess_signal(data):
return data[:, 0] if data.ndim == 2 else data

def analyze_segment(segment, threshold=0):
binary = (segment > threshold).astype(int)
if np.all(binary == 1):
return '0'
elif np.any(np.diff(binary) == -1):
return '1'
return None

def decode_audio_stream(audio_signal, sample_rate, start_sample, samples_per_segment):
decoded_bits = []
current_pos = start_sample
total_samples = len(audio_signal)
segment_count = 0
print(f"Sample: {sample_rate} Hz")
print(f"Points: {samples_per_segment}")
print(f"Start : {start_sample}")
while current_pos + samples_per_segment <= total_samples:
segment = audio_signal[current_pos:current_pos + samples_per_segment]
decoded_bit = analyze_segment(segment)
if decoded_bit is not None:
decoded_bits.append(decoded_bit)
current_pos += samples_per_segment
segment_count += 1
print(f"Total : {segment_count}")
return decoded_bits

def decode(filename="normal_speech_18.wav",
start_time_sec=6.0,
segment_duration_sec=0.1):
sample_rate, data = load_audio_file(filename)
if sample_rate is None:
return ""
audio_signal = preprocess_signal(data)
start_sample = int(start_time_sec * sample_rate)
samples_per_segment = int(segment_duration_sec * sample_rate)
if start_sample + samples_per_segment > len(audio_signal):
return ""
result_bits = decode_audio_stream(audio_signal, sample_rate,
start_sample, samples_per_segment)
return "".join(result_bits)

def from_binary(binary_str):
chars = []
for i in range(0, len(binary_str), 8):
byte = binary_str[i:i+8]
if len(byte) == 8:
chars.append(chr(int(byte, 2)))
return ''.join(chars)

if __name__ == "__main__":
decoded = decode()
print(from_binary(decoded))

运行脚本,即可在控制台获得 flagISCC{Slogan}
20250729160758-2025-07-29-16-07-58

神经网络迷踪

神金题,改为压缩包后缀解开后拿 ISCC 套一下就是 flag

下载附件,是一个 pth 文件,load 模型可以找到一些提示,例如提示:2025ISCC2025KEY!缩小255倍放大255倍
20250729160920-2025-07-29-16-09-20

直接提交ISCC{appl}

八卦

无敌了

下载附件,得到一张 GIF。首先 010 打开,可以发现最后有一段 7z 开头的额外信息
20250729161024-2025-07-29-16-10-24

提取出来得到一个 data.7z,用 7-zip 打开,里面有一个 txt 需要密码
20250729161039-2025-07-29-16-10-39
分析 hint
20250729161051-2025-07-29-16-10-51
首先根据提示 LSB,用 StegSolve 提取
20250729161112-2025-07-29-16-11-12
对应 base64 编码解码得到坤为地。再用 PS 打开 GIF,提取对应的信息,时间及 base 编码,提取出5Lm+5Li65aSp4WY3DZVQWTUJFGI=5rC06Zu35bGv42YLJZNEVHUZZAA=

分别用 base32 和 base64 解出四个卦象为乾为天山水蒙水雷屯水天需

然后观察持续时间,0.2 和 0.3 循环,意为 23,寻找易经六十四卦得到第 23 卦为山地剥

接着由第 1 2 3 5 卦有内容,第 4 6 无内容,1 为有 0 为无得到 111010,对应的十进制为 58,寻找易经六十四卦得到第 58 卦为兑为泽

至此,已经得到全部 7 卦:坤为地 乾为天 山水蒙 水雷屯 水天需 山地剥 兑为泽

按照易经六十四卦中的顺序从小到大排序,再将它们转为上下卦,得到:乾乾坤坤坎震艮坎坎乾艮坤兑兑

解密 7z 压缩包得到U1ZORFEzdFhUa3h2YTNGb2MyOXVNVGswZlE9PQ==,解两次 base64 得到ISCC{WNLokqhson194}