香港AI网络安全CTF挑战赛复盘:Misc、Crypto、Reverse解题思路

admin 2026-07-08 05:11:43 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文复盘香港AI网络安全CTF赛11道题。Misc涵盖DNS编码、语义还原、RAID5恢复与ZIP修复;Crypto涉及seed枚举、RSA参数泄露、MT19937反推及组合攻击;Reverse考察APK签名解密、协议逆向与驱动修复。文章提炼了各方向解题路径与常见踩坑点,实战参考价值高。 综合评分: 90 文章分类: CTF,逆向分析,二进制安全


cover_image

香港 AI 网络安全 CTF 挑战赛复盘:Misc、Crypto、Reverse 解题思路

星航安全实验室

2026年7月5日 11:17 辽宁

在小说阅读器读本章

去阅读

以下文章来源于栈外回声 ,作者Frank

栈外回声 .

记录安全研究、攻防复盘、漏洞分析与技术随笔。关注系统、网络、Web、逆向、密码与现实世界里的安全细节,在代码之外听见风险的回声。

Al x Cybersecurity Challenge 复盘:从 Misc、Crypto 到 Reverse,11 道题的完整解题主线

本文整理香港举办的 Al x Cybersecurity Challenge 中 Misc、Crypto、Reverse 三个方向的赛后复盘。 不堆脚本,不做流水账,重点讲清楚每道题的题型判断、突破口、解题路径和容易踩坑的位置。


00. 先简单说说这场 CTF

这次比赛是Al x Cybersecurity Challenge,在香港举办,主题围绕 AI 与网络安全。官方介绍中提到,比赛希望让参赛者面对 AI 时代的新型网络攻击场景,围绕漏洞发现、漏洞利用、自动化分析等能力展开挑战。

对选手来说,它的题目形式仍然很 CTF:给附件、读题面、分析线索、拿到 Flag。只不过题目背景和设计会更贴近 AI 安全、自动化攻防和真实网络安全场景。

这篇文章不展开太多赛事规则,重点放在解题复盘。我们主要整理其中三个方向:

| 方向 | 题目数量 | 主要能力 | | — | — | — | | Misc | 4 | 流量分析、数据恢复、文件修复、语义关系 | | Crypto | 4 | PRNG、RSA、AES、数论近似泄露 | | Reverse | 3 | Android、协议逆向、驱动交互 |

适合阅读对象:

刚打完比赛,想快速复盘完整思路的同学

准备 CTF 初赛,需要按题型建立解题框架的同学

想把题目从“做出来”整理成“讲得清楚”的同学


01. 总体观感:这 11 题在考什么

Misc、Crypto、Reverse 看起来是三个方向,但这组题的共同点非常明显:

题目并不是让你盲目上工具,而是让你先判断结构。

Misc 里,数据可能藏在 DNS 查询、RAID 成员盘、伪装文件和文本关系中。

Crypto 里,突破口不在“算法名字”,而在随机数状态、RSA 参数关系和生成过程。

Reverse 里,flag 也不是简单搜字符串,而是要理解程序到底信任了什么:签名、协议,还是驱动返回结果。

如果用一句话概括:

Misc 考结构感,Crypto 考边界感,Reverse 考程序行为感。

下面按题目类型展开。


Part 1:Misc

Misc 题型阅读指南

Misc 方向一共 4 题,覆盖:

流量分析

语义谜题

RAID 数据恢复

伪装文件修复

这类题最重要的不是“工具列表”,而是三个问题:

这份数据原本应该是什么结构?

哪些字段、偏移、文件头或长度特征是可信的?

每解开一层后,新的数据类型是什么?

建议做题习惯:

先用 file、binwalk、xxd、strings 建立第一印象

不要只搜索 flag,先判断容器格式和编码链

遇到磁盘、镜像、压缩包时,优先确认元数据和偏移

每一步都保存中间结果,方便回滚和验证


1. Mysterious Code:DNS 流量里的多层编码

题型标签:流量分析、编码识别、ZipCrypto 已知明文

题目描述给出三个关键词:IDS 告警、可疑流量、BASE58。附件是流量相关数据,因此第一步不是爆破,也不是直接搜 flag,而是先确认可疑内容出现在哪个协议里。

分析后可以发现,真正有用的数据藏在 DNS 查询中。将 DNS 查询内容按顺序提取并拼接后,得到的结果并不是明文,而是一条多层处理链:

                                                     DNS 查询拼接      -> Base32 解码      -> 自定义 Base58 解码      -> 得到 ZipCrypto 加密 ZIP      -> 利用 PNG 文件头做已知明文攻击      -> 还原图片并读取 flag

这题的关键判断有两个。

第一,Base32 解码后结果仍然不像普通文本,说明它只是中间层,不是最终答案。很多 Misc 题会在这里卡住:看到“成功解码”就以为已经结束,实际只是进入下一层。

第二,ZIP 使用的是 ZipCrypto,而且内部文件是 PNG。PNG 文件头固定,非常适合做已知明文攻击。相比盲目爆破密码,利用文件格式特征会更稳定。

复盘提醒:

DNS 查询常用于分片外带数据,顺序很重要

编码链每解一层都要重新判断数据类型

看到加密 ZIP 不要立刻爆破,先看加密方式和内部文件名

PNG、PDF、ZIP 等常见格式都有可利用的固定头

最终得到:

                       flag{crack_it_is_to_ezzzzz}

2. Riddler:词语关系里的隐藏密码

题型标签:文本 Misc、语义关系、词向量类比

Riddler 的题面是一份“放错地方的笔记”,里面有很多奇怪短语和误导性描述。它不像传统隐写题那样给出图片、压缩包、流量字段,也不像古典密码那样直接给一串密文。

这题真正的入口在“关系”。

题面反复强调 signal、noise、relationship 一类概念。换句话说,不能只看每个词本身,而要看词与词之间的语义方向。解题时将每行短语拆成语义类比关系,使用类似 GloVe Twitter 词向量的方式做类比恢复,就可以还原出一组可读 token。

恢复出的 token 进一步组合成压缩包密码。用该密码解压附件,即可得到最终 flag。

这题最有价值的地方是提醒我们:

Misc 的“文本题”不一定是藏头、词频、首字母,也可能是语义建模。

复盘提醒:

题面中的“噪声”“关系”“信号”往往不是装饰文字

文本题先不要局限在古典密码

如果每行结构相似,可以考虑它们是不是在表达同一种关系

恢复 token 后,要继续检查是否能作为密码、文件名、路径或 key 使用

最终得到:

                       flag{39fc0ee0f9da4fa397631f0dcba31555}

3. database:降级 RAID 5 里的业务数据库

题型标签:磁盘取证、RAID 5 重建、ext4、SQLite

database 是一道典型的数据恢复题。题面说某公司的 RAID 5 业务服务器备份只保留了一部分数据,需要检查残留证据,尽可能还原有用内容并找到隐藏 flag。

附件解压后可以确认,两个文件都是 Linux Software RAID 1.2 成员。由于 RAID 5 每条 stripe 中包含 parity chunk,即使缺少一个 member,只要布局、chunk size、data offset 等参数正确,仍然可以在 degraded mode 下重建逻辑卷。

解题主线如下:

                                                                 识别 RAID member      -> 读取 RAID5 参数      -> 确认缺失成员位置      -> 跳过 data offset      -> 按 left-symmetric 布局重建逻辑卷      -> 解析 ext4 文件系统      -> 恢复 SQLite 数据库      -> 筛选真正 flag

最容易踩坑的是data offset。Linux md RAID 1.2 metadata 通常不在纯数据区开头,如果重建时不跳过对应偏移,就会把 metadata 当作数据区,后续 ext4 识别会错位。

重建后可以恢复 ext4 文件系统,并找到多份 important.db。SQLite 检查通过后,表内有多条形似 flag 的记录,但前三条记录的分类和说明分别指向 decoy、distraction、red herring。真正的记录是 category 为 System、message 为 Critical system flag 的那一条。

复盘提醒:

磁盘题先判断是不是完整文件系统,还是 RAID/LVM/分区成员

RAID 题不要只看文件头,要读取 superblock 参数

RAID5 缺一盘可恢复,但前提是布局和偏移正确

数据库里出现多个 flag-like 字符串时,要结合字段语义判断真假

最终得到:

                       flag{raid5_recovery_1s_1mportant}

4. ntfs_dump:伪装成 NTFS 的 ZIP 碎片

题型标签:文件修复、magic signature、ZIP 结构、步长隐藏

ntfs_dump 的题面说数据藏在 bin 文件中,flag 格式为 FLAG{xxx}。文件开头有 NTFS boot sector 特征,很容易让人先按完整 NTFS 文件系统去恢复。

但继续观察会发现,文件里充满 ZIP、PNG、JPEG、PDF 等 magic signature 的重复模式,整体不像正常 NTFS。真正的突破点不是“挂载 NTFS”,而是识别出伪装文件中的 ZIP 结构。

关键转折点如下:

ZIP central directory 和 EOCD 能定位到尾部结构

local file header 前两个字节被破坏

原本应该是 PK 03 04,实际前缀异常

修复 local header 后,可以重建出可识别的 ZIP

解出 text.txt 后,还不能直接搜到 flag。文件大小为 4240 bytes,刚好能被 16 整除,这提示数据可能按固定 stride 交错隐藏。对每个 offset 尝试 data[offset::16],在 offset 0 处得到 flag。

复盘提醒:

文件头像 NTFS,不代表整个文件就是 NTFS

大量重复 magic signature 往往说明存在拼接、嵌套或伪装

ZIP 修复要关注 local header、central directory、EOCD 三者关系

固定长度文件可以检查是否存在 stride、列读、交错写入

最终得到:

                       FLAG{DE6DDD7A-5D57-415A-99D7-6C0CE3F688BC}

Part 2:Crypto

Crypto 题型阅读指南

Crypto 方向一共 4 题,表面上都是常见算法:Base64、Python random、RSA、AES、MT19937。

但真正的考点不在“背算法名字”,而在生成过程。

做 Crypto 题时建议先问:

随机数是怎么产生的?

随机数被消耗了几次?

RSA 的辅助值泄露了什么关系?

加密前后的结构是否能提供已知明文?

结果是否能被格式校验?


1. CardSeed:可重现 shuffle 的逆向

题型标签:Python random、seed 枚举、置换还原

CardSeed 的附件中只有一个较短的 Python 脚本。它先将 flag 做 Base64,再用 random.seed(key_number) 初始化随机数,随后对字节数组执行 shuffle,最后输出被打乱后的结果。

题目的保护机制并不复杂:

key_number = randrange(999999)

,搜索空间只有 999999

Python random.shuffle() 是伪随机过程

seed 相同、列表长度相同,shuffle 产生的置换就相同

Base64 只是编码,不是加密

解法就是枚举 seed,重建同样长度的索引数组,对索引数组执行同样的 shuffle,然后把输出字符串按逆置换放回原位置。每个候选结果再做 Base64 validate,并检查是否符合 flag{…} 格式。

这题非常适合用来理解“随机”和“不可恢复”之间的区别。

只要 seed 空间足够小,所谓随机打乱就会变成可穷举的置换。

复盘提醒:

看到 Python random 要第一时间检查 seed 来源

shuffle

可以通过索引数组还原置换

Base64 validate 是很好的候选过滤器

不要把编码当加密

最终 seed 为 614033,得到:

                       flag{69d27b78-b762-406e-962d-c21afd6b0ba0}

2. Drift:RSA 中“很小的误差”并不小

题型标签:RSA、phi(N) 近似泄露、小范围枚举

Drift 的题面问得很直接:一个转换后的 RSA 指数,只和 phi(N) 的倍数差了一点点,这点误差真的安全吗?

附件逻辑可以抽象为:

                       a = k * phi(N) + x

其中 k 很小,范围大约是 2 到 96;x 只有 150 bits。对于 1024-bit RSA 来说,这不是“无害噪声”,而是对 phi(N) 的高精度近似泄露。

原因在于:

                       phi(N) = N - (p + q) + 1

一旦能恢复 phi(N) 或者 p + q,就可以通过二次方程分解 N。实际解法先枚举小范围的 k,再把问题转化为寻找 p + q 的小误差。正确的 S = p + q 会让:

                       D = S^2 - 4N

成为完全平方数。找到正确 S 后恢复 p、q,进一步计算私钥 d 并解密密文。

复盘提醒:

RSA 题里所有“接近 phi(N)”的值都要高度警惕

小范围参数不要怕枚举,先把数学关系写清楚

能恢复 p + q,就基本等价于能分解 N

完全平方数检查是 RSA 分解中常用的验证方式

最终得到:

                       flag{rsa_exponent_transforms_need_error_bounds}

3. LuckyRand:从 AES-CBC 密文反推 MT19937 状态

题型标签:AES-CBC、MT19937、状态恢复、IV 重组

LuckyRand 把受保护的信息混入大量看似随机的数据中。题目使用 AES-CBC,但关键不只是 AES,而是 PRNG 的生成与消耗顺序。

程序中,明文结构大致为:

                       padded_flag || 160 个 PRNG 生成的 128-bit block

密文共 163 个 block,因此 flag padding 后占 3 个 AES block,也就是 48 bytes。后面的 160 个 block 可以结合 CBC 解密关系还原出 PRNG 输出,再加上公开 key,可以拿到足够多的 MT19937 输出。

核心步骤如下:

                                                                 利用 CBC 关系恢复 PRNG block      -> 每个 128-bit block 拆成 4 个 32-bit 输出      -> 对 tempered output 做 untemper      -> 恢复 MT state word      -> 处理缺失的 IV 对应 word      -> 利用 CPython twist 原地更新细节求缺失状态      -> 重组 IV      -> 解密前 3 个 block 得到 flag

这题最容易错的点是 CPython 的 MT19937 twist 并不是“同时更新整个数组”,而是原地更新。最后一个 state word 的计算会用到已经改写过的 mt[0]。如果忽略这个实现细节,方程关系就会错。

复盘提醒:

AES-CBC 题要写出每个 block 的依赖关系

MT19937 输出足够多时可以恢复状态

tempered output 需要 untemper 才是内部状态

具体语言实现细节可能影响恢复公式

最终得到:

                       flag{75b24dd7-e758-4587-8d34-ccffbe81eb16}

4. RsaComb:把散落的 RSA 线索串起来

题型标签:RSA 组合题、三次方根、Wiener Attack

RsaComb 是一道 RSA 风格的组合题。题面给了几组看起来不太寻常的辅助线索,关键不是单点突破,而是把它们按依赖关系串起来。

攻击链可以概括为:

                                               从 Gift^3 恢复 Gift      -> 恢复辅助公钥 gift_e_pub      -> 恢复真实 RSA 公钥 e      -> Wiener Attack 恢复私钥 d      -> 解密

第一步利用的是三次方根关系。恢复 Gift 后,可以进一步解出辅助公钥信息。随后再从辅助关系中恢复真实 RSA 公钥指数 e。

最后的关键是 Wiener Attack。真实私钥 d 满足 Wiener attack 条件,因此可以通过连分数展开从 (e, N) 恢复 d。拿到 d 后,就回到标准 RSA 解密流程。

复盘提醒:

RSA 题里的辅助值不一定直接泄露 p、q 或 d

但只要能恢复 e,或者约束 d 的大小,就可能落入经典攻击

三次方根要先判断是否没有模约束或没有溢出

Wiener Attack 的入口是“小私钥 d”

最终得到:

                       flag{rsa_comb_v2_cube_root}

Part 3:Reverse

Reverse 题型阅读指南

Reverse 方向一共 3 题,分别对应:

Android APK 签名校验

自定义 socket 通信流程

Windows 驱动交互与 IOCTL 校验

这三题的共同点是:flag 不在显眼字符串里。

真正要还原的是程序的信任逻辑。

做 Reverse 题建议按这个顺序推进:

先跑起来,观察输入输出和报错

找到关键函数,而不是全量反编译所有代码

判断 flag 是被解密、被验证,还是由通信流程返回

把程序依赖的上下文补齐,例如签名、密钥、证书、驱动连接

最后再写脚本复现逻辑


1. CodeSign:APK v2 签名参与解密

题型标签:Android 逆向、APK v2 签名、SHA1、异或解密

CodeSign 是一道 Android 逆向题。题面说移动保险库显示访问已被允许,但秘密没有出现。分析 MainActivity 后可以发现,程序确实会在按钮点击后尝试把解密结果写入 tv_flag,但 UI 层又提示输出被禁用。

真正的核心在 decrypt() 所需的 key。程序通过 SignUtils.getAppSignature() 获取当前 APK 的签名证书,对 DER 数据做 SHA1,然后参与异或解密。

这里有一个关键坑点:

该 APK 使用 v2 签名,并没有传统 META-INF/*.RSA 证书文件。不能按老 APK 的方式去找证书,而要从 APK Signing Block 中提取证书 DER,再计算 SHA1。

拿到签名 SHA1 后,将其作为 key 与 SECRET_DATA 做异或即可恢复 flag。还有一个小细节:反汇编 fill-array-data 时末尾附近可能出现对齐补位 00,但它不属于密文,不能参与异或。

复盘提醒:

Android 签名题要先判断 APK 签名方案版本

v2 签名证书在 APK Signing Block,不在传统 META-INF 路径

反汇编数组要注意对齐补位

UI 提示不一定等于真实失败,关键看解密函数依赖

最终得到:

                       flag{ICQ_Dyn4m1c_Byp4ss_K1ng}

2. SimpleSocket:RSA 保护 AES key,AES 解 flag

题型标签:协议逆向、RSA-OAEP、AES-ECB、PEM 修复

SimpleSocket 附件中有 Python socket 通信逻辑,以及三个数据包文件。题目要求逆向自定义通信流程,还原最终内容。

分析后可以看出通信结构:

packet2

保存 RSA 私钥

packet3

是 RSA-OAEP 加密后的 AES key,长度 128 bytes

packet1

是 AES-ECB 加密后的 flag,长度 48 bytes

这里不能只根据变量名猜数据含义,而要结合数据长度和加密算法特征判断。RSA 1024-bit 密文长度正好是 128 bytes,AES 密文长度是 16 bytes 的倍数。

另一个细节是,packet2 中保存的是字面量 \n,不是真实换行。导入 PEM 私钥前,需要先把字面量 \n 替换成真实换行。

完整解题流程:

                                               修复 PEM 私钥      -> RSA-OAEP 解出 AES key      -> AES-ECB 解密 packet1      -> unpad      -> 得到 flag

复盘提醒:

协议逆向要结合长度、算法块大小和文件内容判断角色

RSA 密文长度通常等于模数长度

PEM 中的换行经常会被转义,需要修复

AES 解密后记得处理 padding

最终得到:

                       flag{28b0e93d-1b8c-40ff-9075-2049102f1e26}

3. drive:修复缺失符号,再理解 IOCTL 校验

题型标签:Windows 驱动、用户态交互、IOCTL、约束求解

drive 是 Reverse 中难度最高的一题。题面提示公司的驱动程序有 bug,连接程序也连不上,并给出了缺失符号的 md5。

这题第一阶段不是直接找 flag,而是先回答一个更基础的问题:

用户态程序为什么连不上驱动?

通过分析可以定位到设备名或导入符号相关问题,需要先修复程序,使用户态程序能够重新与驱动通信。

连接恢复后,重点转向 IOCTL 流程。用户态程序会向驱动发送输入,驱动内部执行校验并返回结果。逆向驱动校验逻辑后,可以把它整理成可求解约束,再编写脚本搜索满足条件的输入。

这题和普通字符串解密题不同。flag 不是静态藏在某个 rodata 中,而是由驱动逻辑验证或生成。因此必须先恢复程序运行链路,再逆向 IOCTL 校验算法。

复盘提醒:

驱动题先确认用户态和内核态通信是否真的建立

IOCTL code、输入缓冲区、输出缓冲区都要对应起来

缺失符号、设备名、导入表问题可能是第一层门槛

校验逻辑复杂时,可以转成约束或搜索问题

最终得到:

                       flag{wnNCZJbBOqL3QA1C1cypiKYII4}

04. 三类题的共同方法论

Misc:先看结构,再谈工具

Mysterious Code、database、ntfs_dump 都说明:如果一开始不知道数据是什么,工具只会给出一堆噪声。

先用文件头、长度、协议、字段分布建立结构假设,再去验证,效率会高很多。

可以记住这个顺序:

                       识别格式 -> 判断容器 -> 处理偏移/损坏 -> 解码/解密 -> 验证结果

Crypto:随机数不是玄学,辅助值不是装饰

CardSeed 和 LuckyRand 都围绕随机数展开。只要 seed 空间小,或者输出足够多,随机过程就可能被还原。

Drift 和 RsaComb 则说明,RSA 题中的近似值、辅助值、异常指数都值得认真分析。

可以记住这个顺序:

                       读生成逻辑 -> 写数学关系 -> 找泄露边界 -> 枚举/恢复 -> 格式校验

Reverse:还原程序相信了什么

CodeSign 信任 APK 签名,SimpleSocket 信任协议分层,drive 信任驱动 IOCTL 校验。

逆向题里,真正的 flag 往往藏在“程序为什么相信这个输入或结果”的逻辑中。

可以记住这个顺序:

                       运行观察 -> 定位关键函数 -> 补齐上下文 -> 复现逻辑 -> 输出结果

05. 写在最后

这 11 道题的难点并不在“工具够不够多”,而在分析时能否先建立正确的结构假设。

遇到 Misc,不要急着跑全套工具,先判断数据原本应该长什么样。

遇到 Crypto,不要只看算法名,先看随机数、参数和辅助信息是怎么产生的。

遇到 Reverse,不要只搜字符串,先问程序到底信任了什么。

这也是 Al x Cybersecurity Challenge 这类 AI 网络安全赛事给人的一个启发:自动化系统可以帮助我们跑得更快,但真正决定方向的,仍然是对题目结构、攻击边界和程序行为的理解。

参考:Hong Kong SeCAI 官方网站


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:星航安全实验室 《香港 AI 网络安全 CTF 挑战赛复盘:Misc、Crypto、Reverse 解题思路》

评论:0   参与:  0