ADCTF 2025 个人出题记录
Forensic
Dangerous Worm
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Dangerous-Worm
出这道内存取证主要是在羊城杯里面做到了一题你也是旮旯给木大师?,那个题目是病毒分析+内存取证,给了我启发,于是我也决定出这么一题来玩玩。
编写病毒
首先是怎么编写病毒,我的本身就是用 AES-CBC 只加密部分文件,然后再把密钥保存到电脑里头,向量用程序自身的
于是就简单的写了一个加密用户桌面等文件夹的一个病毒程序(源码在仓库里可以去看),顺带加了个防呆设计(避免我自己运行了病毒)
1 | def main(): |
构建靶机(Win7,失败)
因为永恒之蓝(MS-17-010/CVE-2017-0144)在当时太有名了,并且在利用上也有很多成型的方案,于是我打算打一个永恒之蓝
在最开始,我使用的是 Windows 7 x64 Professional SP1,我先把我的病毒打包好,然后尝试直接打永恒之蓝,并把病毒放上去直接运行,结果不出意外的就出意外了
当我在 shell 里面直接运行我的病毒,我的 shell 直接就没了,变成了 More? meterpreter >,并且也没有实际效果
我最开始还想着是身份问题,因为永恒之蓝打上去以后是 nt authority\system,所以此时不是我自己创立的 Luminoria 账户,可能会导致我的 %APPDATA 无法展开和 %USERNAME 获取错误,于是我直接改了一个获取用户名的方案
1 | import os |
通过这个方式直接获取系统内的用户,并对每个用户的文件进行加密
完成了以后还是不行,而且一点日志都没有,我排不出错误,于是我决定在靶机里面手动运行
结果不运行还好,一运行就是一个大坑
这分明就是运行库的问题呀!!!
然后我就在想能不能 Win7 编译 Win7 跑,于是我用快照回退到有 VMTools 的那个版本,装了一个 Python 并编译,然后再拿过来,结果还是报一样的错误
看来没有必要的安全补丁的话,都没有对应的环境,只好作罢,换系统
构建靶机(Win10,成功)
我突然想到,当时永恒之蓝出来的时候,Win10也没能幸免,说明那个时候的 Windows 10 是有这个问题的
于是我就去找 17 年左右或以前的 Windows,最后找了一个 Windows 10 1511(16年4月)
刚开始装的时候,VMWare 告诉我可以建议安装,我还说这么好,省事了,结果是给自己找麻烦了
VMWare 在建议安装的时候会带上 VMTools 的安装,在这个时候就会打上必要的补丁了,搞得我一直打不通,没办法,手动装吧
于是就见到了早期 Windows 10 还没有大型 OOBE 的时候的 UI
装好了以后,尝试跑一个永恒之蓝,发现打不通
搜了一下别人的经验,要调本地组策略
于是在 gpedit.msc 里面,把 可匿名访问的网络共享 调成 \,然后把 可匿名访问的命名管道 设置成
1 | COMNAP |
然后保存,发现可以连上了,但是在 kali 里面一跑 run 就蓝屏,错误的模块是 srvnet.sys,搜了一下告诉我是 payload 选错了,要选 exploit/windows/smb/ms17_010_psexec
1 | msf exploit > use exploit/windows/smb/ms17_010_psexec |
然后重新设置一下 RHOSTS
1 | msf exploit > set RHOSTS 192.168.237.151 |
然后 run,就成功得到后门连接了
进行渗透
首先我把两个文件传了上去,一个是前阵子在 Github 发现的影子账户创建工具
还有一个是我自己做的马,我先用这个工具创建了一个影子账户
这样就完成了第二题的出题,答案应该为 PaffCream$
然后我就把这个 a.exe 删掉了,不留痕迹,然后跑我的马
因为还是发现直接在 shell 里面执行不了我的马,所以我把马传到了用户的 shell:startup 里面去
1 | meterpreter > upload 安全中心.exe "C:/Users/Luminoria/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup" |
这样就可以实现用户重启系统/重新登录以后触发,然后去 shell 里面直接触发一次重启
1 | shutdown -r -t 0 |
重启并自动登录后,机子就弹出了黑框框了,然后直接就把东西给加密了
获得内存
我没用 Dumpit.exe,不知道为啥 Dump 出来的有问题,所以本文先不管这个方法
因为我运行在 VMware 里面,所以直接用 VM 的工具就行了
在安装目录有一个 vmss2core.exe,可以转储内存为 dmp 文件(需要管理员权限运行)
1 | .\vmss2core.exe -W8 Vuln10-12a24566.vmss Vuln10-12a24566.vmem |
然后就能在当前目录得到 memory.dmp 文件,就是内存转储了
Gering Ding Ding Ding
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Gering-ding-ding-ding
出这个题目最初的想法来源是本来想出 Web3 的题目的,奈何自己确实对 Web3 不熟悉,而我想的取证三个方向(流量、硬盘、内存)中,硬盘取证缺少那么点点子
所以在做了一点研究以后,发现 Firefox + MetaMask 的取证是可行的,所以就出了这个题目
对 LocalStorage 的提取
最开始其实我是用的 Edge,因为那天早上我在上数据结构的实验课,我在我的黑苹果上用 Edge 试了一下,当时是感觉可行,所以最开始是用了 Edge 出的
但是我在网上找到的 Chrome 那个方法(Edge 用的也是 Chrome 内核),Edge 出来的插件的 ldb 里面不像文章所说的有 KeyringController 关键词,后面用 Chrome 也有一样的问题,所以只能放弃 Chrome 内核的浏览器,用 firefox 那篇文章的那个方法
数据处理与密码爆破
用了 Firefox 以后,提取数据其实不是什么问题,问题出现在了我爆破这一节
在文章 当大狐狸遇上小狐狸——Win11火狐Metamask取证小记 | 9C±Void’s Blog 中提到,hashcat 的 26600 不能爆破出来,要用 26620 或者是后面那个 26650,我先用的 26620,发现会爆格式不正确的问题,但是我也没细看
1 | hashcat -a 0 -m 26620 metamask_hash.txt rockyou.txt |
我就去找 26650,我都翻遍了整个互联网(包括 web archive),都没有找到备份,那没办法了,只好继续看看怎么用 26620 了
后面我看到了文章里面这句标黄的字
再看看我的 hash,发现有 rounds=,删掉了以后就能够用 26620 爆破了
再往后都是常规操作了,SRP 得到钱包再得到密钥,此处就不再赘述了
原神,启动!
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Its-Genshin-Time
出这个题的背景主要是,我在当时刷到了一条关于 Magisk 模块安全性的新闻(?)
虽然说这篇帖子的这个贴主明显就是缺少经验了,但是安装来路不明的 Magisk 模块确实是很危险的一件事情,所以我就想以这个背景来出一个题目
至于为什么会选择原,是因为之前看到过一个比较搞事的模块,叫「自动下载原神」,会在每次开机的时候检测手机里是不是存在原神,如果没有的话就会自动下载安装
然后我就去稍微写了一个 Magisk 模块
Magisk 模块
我的想法是这样的,毕竟原本体还是太大了,所以我选择下的是云原神
在设备开机的时候先进行一次检测,如果不存在则下载,并发送通过云控服务器获取配置,“窃取”一定的设备标识及数据并发送到远程服务器,随后进入 loop,持续检测,只要云原被删除了就重复整个过程
而具体的操作,是通过云控脚本进行的,于是简单做了一个服务器,并放了一个云控脚本
而我在 Magisk 模块的 system.prop 里面,写了名为 challenge.secret.info 的键值对,这样在 Magisk 模块安装的时候,这个键值对就会被加入到 system.prop 里面去
然后在按照 Magisk 模块的标准稍微打包一下,就完成了
抓包
我在模拟器里面装了 termux 来用 tcpdump,直接去这里下一个 tcpdump
然后传入模拟器运行,结果需要 root 权限,那没办法,给了,给了以后,在 tcpdump 启动的情况下不断对着自动安装的云原点卸载就好了,期间还访问了一下网易 mumu 的游戏中心,掺杂一些干扰数据,就完成了
Misc
BaseGDUT BaseHajimi
题目仓库:
https://github.com/GDUTMeow-Challenges/Challenge-BaseGDUThttps://github.com/GDUTMeow-Challenges/Challenge-BaseHajimi
出这题主要是刚开学那会有人想学CTF,私信问我 Base64 是什么
然后我想,Base 本身是存在编码表的,而且我们平时也存在换表这一操作
所以说,我直接出个自定义编码表 Base8,来考考选手对 Base 系列的基本理解
然后就跟 ?CTF 撞点子了 =-=
在选编码表的时候,我想着既然是校内赛,就选一个跟学校相关的编码表,最后敲定的是 GDUTgdut 这八个字符,使用 = 填充
反正爆来爆去也就 8! 种情况,很快就出来了,其他也没啥好讲的了
补充
是的,本来是上面的都是这题的设想的,但是某一天,Unknown 在群里面提了个建议,改成 Hajimi,于是我就改成用 哈基米哦南北绿豆 几个字符换掉了原来我的 GDUTgdut 八个字符,变成了 BaseHajimi
Click the Circles
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Click-the-Circles
出这题的原因主要是我个人在玩 Osu!
想着能用 Osu! 做些什么题目,本来想把题目放进铺面(指 note)里面的,但是后来想想还是算了,又不是所有人都会玩音游
然后就去翻了一下 Osu! 的铺面文档,发现了放在书签位置的话,就可以在不影响铺面正常元数据和铺面游玩的情况下放信息
然后我又想到了 moeCTF 2024 的海报题,那个题目把摩斯电码放到了海报里面,所以我也学着用摩斯电码隐藏信息
而摩斯电码是部分大小写的,这点在 ADCTF 2024 吃过亏,所以我限定了字母要小写
然后花了点时间找了个合适的谱子,把时间序列往上面一放就搞定了
知识问答
本来没打算出这种题目的,但是之前跟网络中心开会的时候他们的意思是还是想要有科普题,然后我就去找了个最近的题库
题库来源于中国社会科学院大学网络中心:https://nc.ucass.edu.cn/info/1160/1594.htm
然后随便撸了一个前端,就这样了
Web
Worthit
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-WorthIt
题目设计
这个题目其实最开始是我的个人项目,当时心血来潮写了一个这个程序,然后我在最开始在前端 js 采用的是拼接字符串的方式(没错这很危险)
因为我想的是,这东西是你个人使用的,然后我又加了 httponly 的 Cookie 标识,所以其实 XSS 并没有什么可以利用的
但是当时让 Rusty 测都测了,还是给修了吧,然后我顺带拿这个来出题好了
从源码改到题目
就像我上面说的,我其实加了 httponly 的标识,所以我先给它删了;又考虑到我们的靶机出来都不会上 https,所以我又把 secure 删了
然后我稍微添了点乱,禁用了 script 关键词,但是聪明的你一定能想到其他的关键词吧
Y2K Bank
题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Y2K-Bank
题目设想
这题其实最开始的设想不是这样的,我一开始没有打算把它出成与银行存款、千年虫等各种元素相关的题目
我最开始的设想是,在购物平台购物的时候,购物车里经常会让我们选择购买数量,这个时候如果我输入成负数,就可以让购物平台倒欠我的钱,给我米,然后攒够钱来买 flag,是这样设想的
但是吧,在出上面那个 Dangerous Worm 的时候,找那个 2114 年 5 月 14 日的星期的时候,Windows 这里直接就不显示农历了
然后我就想起来了有 Y2K 这个东西,就想基于这个东西出题,而当时受 Y2K 威胁最大的其实是各种金融机构,所以我就一改,把这个背景改成了银行
构建后端
后端这一块,因为最近已经从 flask 转到 FastAPI 上面了,所以我很自然的就用了 FastAPI 来弄后端
在实现 Y2K 的时候,我在想要怎么实现 Y2K 的这个效果,因为本身 Y2K 的出现就是因为计算机采用两位数字存储年份(前面默认为 19,拼接得到 19xx),然后就采用了输入数字与 100 取模的方式,得到尾巴两位,然后与 19 拼接,就得到了千年虫的效果
那么问题就是,要怎么让日期变得可以更改,最后我决定让前端传入日期(这显然是不合规的,也不应该出现在任何一个银行系统中,但是 CTF 题目嘛,倒也无所谓?),这样用户就可以通过 Yakit 或者 Burpsuite 拦截以后直接修改,或者用 Hackbar 直接发啥的
构建前端
我个人的设想就是用银行的 ATM 界面,所以直接把需求给 v0 让它帮我写了,没啥好说的,然后因为绿色的我觉得看久了还是眼睛挺痛的,于是又加了一个 modern 版本的开关,可以切换(你发现了吗)
Crossy Road
这个倒没啥技术含量,只是之前抓很多网站的请求的时候,DevTool 会被 ban 或者是会被无限 debugger,所以就弄个这个题目
DS
DSFileChecker
这是一个平台(并非题目),因为前阵子打羊城杯和去年打羊城杯,数据安全这里都有一个东西叫做 DAS File Checker 来做校验(安恒的平台),而去年的网安卫士,我们是没做这个的,是让选手直接把结果拿去算 md5 得到结果,这样就导致了选手其实不知道自己对了多少错了多少,并且要求 100% 正确才能得到 flag(而 DAS File Checker 允许通过某一个正确率,例如 95%,即可获取 flag),所以我就打算做那么个平台
基本上,正确率的计算基于以下原则
- 将标准答案的数据读取进入内存,并生成唯一标识
- 统计行数,从行数上先查看是否有多余
- 计算正确行数,对于每一条数据,取出现位置较小的那个行,并比对数据
- 如果有多余数据,会导致分母变大
- 最终计算方法为
Accuracy = CorrentLines / (AnswerLines + AdditionalLines)
所以这样计算的话,就会让冗余数据稀释正确率,达到了我的目的
随后就是对各种变量的设置,我设置了各种 flag 和 accuracy 变量,accuracy 变量是作为正确率阈值的,当选手的正确率达到了这个规定的阈值,才给出 flag
然后还做了对各种平台的 flag 注入的适配(这些 flag 变量是从探姬的 https://github.com/CTF-Archives/ctf-docker-template 里面发现的)
1 | # Flag will be read from env |
采用了逐级 fallback 的方式来获取 flag,但是后面问了 AI,说其实可以写的更好看,于是改成了
1 | # Flag will be read from env |
找回订单
出这个题目纯属是因为当时在羊城杯看到 DS4 那个题目太宝宝巴士了,刚好需要一些宝宝巴士的题目就拿过来了
把数据拿过来的时候我顺带就进行了一些修改和要求的增加,避免有人搜到原题直接一把梭,大致如下
- 邮箱里面的
meishu-tech.com->adctf.org - 产品里面的
美枢科技->ADLab - 增加了还原用户名的要求
- 增加了还原产品名的要求
所以如果对 sql 语句熟悉的话,可以直接把东西拿出来以后写一个脚本一把梭,实在是没什么难度
Plain HTTP Data
这个题目也是想的出的宝宝巴士一点,所以就出了这个直接 http 明文传输可直接提取处理的题目
最开始,我的数据量其实在 10W 的级别,但是我在用我自己的 Wireshark 提取的时候,想着肯定有人用左上角文件导出对象来保存的,不试不要紧,一试就发现在这个过程中,数据量太大了,Wireshark 容易直接罢工
那没办法,宝宝巴士还得是宝宝巴士,所以就减小数据量到 1k 了,然后我还把一些干扰数据给剔除了,才保存的附件,应该……能做出来吧……
群 Bot 编写
因为之前都有群播报 bot,并且 ?CTF 的播报 bot 是正常使用的,所以我就想着弄一个 Bot,可以播报前三血和公告啥的内容
问了一圈,发现说 napcat 好用且稳定,然后我先去弄了一个 napcat,并登录了我的小号
然后抓了一下 A1CTF 平台的 API,并做了一个简单的小玩具
A1CTF-Journalist: https://github.com/GamerNoTitle/A1CTF-Journalist
反正主打一个能用就行,就跑上了
倒计时海报
用 canvas 做的,凑合看看吧































