文章总结: Solar应急响应团队举办了2025年11月公益月赛,公布了前三名选手n0o0b、butt3rf1y和CloneWith。比赛围绕应急响应方向命题,重点考察选手在应急响应核心技能的掌握。文档详细解答了emergency、3_idiots和2700勒索病毒排查三个题目,其中3_idiots通过CHM载荷、JS混淆、异常处理劫持等技术综合考查选手能力,2700勒索病毒排查题目涵盖了勒索家族识别、数据恢复和钓鱼溯源等内容,提供了实用的应急响应技术指导。
综合评分: 88
文章分类: 应急响应,CTF,恶意软件,逆向分析,实战经验
2025-11月Solar应急响应公益月赛排名及官方题解
原创
solarsec
solar应急响应团队
2025年12月2日 13:20
山东
点击蓝字 关注我们
1.11月月赛排名
2025年11月Solar应急响应公益月赛已圆满结束。以下为最终WP提交情况(部分选手因未在规定时间内提交WP,不计入最终排名)
以下为11月月赛最终排名结果(分数相同,按照解题速度排名)
本次月赛榜已完成总分统计(积分相同则并列排名)。最终恭喜以下三位选手获得本年度Solar应急响应公益月赛前三名:
第一名:n0o0b
第二名:butt3rf1y
第三名:CloneWith
本周内我们将联系各位师傅确认收件信息,并安排奖品寄送事宜。
2.平台介绍
天狩·网络安全竞赛平台是由 思而听网络科技有限公司 推出的一款Saas化部署的网络安全竞赛平台。平台可满足CTF、AWD、渗透赛等各种赛制的举办需要,可以满足万人同时竞赛的需要,支持最高全国级的网络安全大赛承办。具备竞赛中心、竞赛管理、练习场、试卷管理、赛题管理、人员管理、报名管理、数据中心、日志管理、防作弊机制、3D大屏等功能模块,能够全面、精准地考核选拔网络安全人才。
3.赛事回顾
在11月举行的Solar应急响应公益月赛中,共有282位选手积极参与。本次月赛围绕应急响应方向精心命题,全面考察选手在应急响应核心技能上的掌握程度。值得特别指出的是,在Reverse模块的3_idiots中,共有6人完整解出该题目。
本题通过 CHM 载荷、JS 混淆、异常处理劫持、自修改代码与密码哈希验证链路的多层嵌套,综合考查选手对逆向工程、动态调试与加密算法理解的能力。题目文件以 CHM 为入口,打开后界面正常,但在索引页中隐藏了一个可执行文件。提取 index.html 后可看到页面中包含一段经 XOR 加密的 JS 代码,解密执行后利用 COM 组件调用系统自带的 hh.exe(CHM 反编译器),将内部的 test.exe 释放到公共目录并执行,因此核心逻辑实际位于该 EXE 内。
将 test.exe 导入 IDA 可观察到程序首先从注册表读取名为 pswd 的字符串作为输入密码,并在后续流程中进行计算与校验。全局函数指针位于 0x4210,具有初始化、调用与归零三处交叉引用;初始化时其指向一个简单字符串比对函数,似乎是“正常路径”的正确答案校验。然而进一步分析 0x2110 函数发现情况并非如此:该函数首先检查密码是否由小写 16 进制字符组成,随后进行一系列 Patch 操作,修改了位于 RVA 0x3218 的异常结构体,将全局函数指针清零,从而在后续调用处强制触发异常。
跟进补丁位置可确认程序在运行时动态添加了自定义异常处理器,其跳转地址为 0x1ee0。进入该函数后,程序再次读取全局密码并弹框提示,此时提示内容由原先的 “sha256” 变为 “md4”,表明若输入为 16 进制小写形式,将走异常路径逻辑。函数内随后调用 0x11f0 执行一个带 ping 延时的自删除命令,删除由 hh.exe 释放的全部反编译目录(包括自身),并以 ExitProcess 结束流程。
异常处理器继续将密码传入 0x1e30,先恢复先前异常结构体被修改的 QWORD,再调用 0x1000 计算输入密码的宽字符长度,由此可确定密码长度必须为 4。之后程序进入 0x1d10,对成功提示字符串执行 Patch,将字符 L’4′ 加一,从而将提示从 “md4” 修改为 “md5”,暗示最终 flag 的提交格式需要使用 md5。
进入 0x1b50 与随后调用的 0x13b0 可看到 SHA-3 相关常量,结合题目名 “3_idiots” ⇒ “3 傻” ⇒ SHA-3,可判断此处实现了 SHA-3(sha3-256)哈希函数。异常路径最终逻辑为:对 4 字节密码进行 SHA-3-256 两次哈希,将结果与 32 字节常量数组比对;若相等,则弹出前一步已被改写为 “md5” 的成功信息。由此可直接抽取目标哈希值,通过 Python 枚举全部 4 字节小写 hex 字符串(共 16⁴ = 65536 种)进行爆破。
4.11月月赛WP
emergency
1.提交黑客的IP地址:10.0.100.69
2.提交黑客初始连接的PHP一句话木马密码:shell
3.提交黑客通过初始连接一句话木马后创建新的一句话木马文件的MD5:91a29f36879b024d661851b7765f3969 4.提交黑客创建的不死马的密码:4aad625950d058c24711560e5f8445b9
5.提交黑客上传的恶意文件(远程控制木马)的名称:shell.exe
6.提交黑客上传的恶意文件(远程控制木马)的MD5:0410284ea74b11d26f868ead6aa646e1
7.提交黑客上传的恶意文件(远程控制木马)的端口:4444
8.请提交黑客创建用户账户的用户名:hidden$
9.请提交黑客创建用户账户的密码:P@ssw0rd123
10.请提交黑客创建用户账户的时间:2025/11/20 16:13:32
提交黑客的IP地址
获取方式1
Nginx日志中,发现10.0.100.69大批量进行敏感路径扫描。
并且访问敏感文件进行交互
获取方式2
从捕获流量中筛选出HTTP数据包,发现请求了shell.php的可疑请求
提交黑客初始连接的PHP一句话木马密码
获取方式1
根据log日志数据分析,黑客通过cache目录下的configs.cache.php到shell.php,再到bsm.php和.config.php
一次推断,可能前面几个文件对后面的木马有所关联。
目录下没有shell.php,但是我们的日志里是访问成功,有可能被删除了。
不过我们确实在configs.cache.php中找到了一句话木马的内容,其实这也是这个CMS的一个漏洞,也被公开过很久了。
所以这里的flag是flag{shell}
获取方式2
该说不说,这道题给出了流量包其实就非常降低难度了
同样可以获取
提交黑客通过初始连接一句话木马后创建新的一句话木马文件的MD5
前面看了日志,黑客通过configs.cache.php创建后,访问了shell.php,但是我们没找到啊?
其实也可能是被删除掉了
Autopsy加载一下磁盘
找到了一个被删除的php文件
保存下来之后,使用工具或命令获取其内容
flag{91a29f36879b024d661851b7765f3969}
提交黑客创建的不死马的密码
这个就简单了,根目录下的.config.php应该就是了
flag{4aad625950d058c24711560e5f8445b9}
提交黑客上传的恶意文件(远程控制木马)的名称
已经提到了是远程控制木马了,按理来说是一个exe程序,我们先看看有没有什么exe程序被创建/上传。
观察流量包发现,这是一个Antsword的流量包,根据特征可以得到文件上传的特征包。
比如上面这个图片的文件
上传后的文件名就是bsm.php
内容就是下图中的不死马内容
我们可以过滤一下:
ip.src == 10.0.100.69 && http.request.method == "POST"
文件上传的话,我们找一下Length比较大的数据包
第一个1251长度的我们已经看过了,看下下一个
那这里就是shell.exe了-> flag{shell.exe}
提交黑客上传的恶意文件(远程控制木马)的MD5
还是上一题的流量包
保存下来
flag{0410284ea74b11d26f868ead6aa646e1}
提交黑客上传的恶意文件(远程控制木马)的端口
火绒剑方案或沙箱方案都是可行的
flag{4444}
请提交黑客创建用户账户的用户名:hidden$
流量包分析得出,用户名为hidden$
flag{hidden$}
请提交黑客创建用户账户的密码:P@ssw0rd123
上一步的结果中也包含了,flag{P@ssw0rd123}
请提交黑客创建用户账户的时间:2025/11/20 16:13:32
响应时间,转换为UTC+8
from datetime import datetime, timedelta, timezone
input_time_str = "Thu, 20 Nov 2025 08:13:32 GMT"
dt_utc = datetime.strptime(input_time_str, "%a, %d %b %Y %H:%M:%S GMT").replace(tzinfo=timezone.utc)
utc_plus_8 = timezone(timedelta(hours=8))
dt_local = dt_utc.astimezone(utc_plus_8)
formatted_time = dt_local.strftime("%Y/%m/%d %H:%M:%S")
print(f"转换结果: {formatted_time}")
3_idiots
题目文件结构:
chm文件,打开.
一切正常.
打开索引,发现exe文件.
提取之,双击打开,无回显.
提取index.html,打开.可以发现,这就是chm一打开时候的那个页面的源码.
该网页使用异或算法加密了一段数据,解密后eval,判断应为js代码.
解密得到js代码.
格式化后可以看出,代码两次滥用com组件执行命令行,调用hh.exe(win自带的chm反编译器)释放test.exe到公共目录,然后执行.断定核心代码应该在test.exe中.
将test.exe拖入ida.
打开注册表中的用户内容,读取其中的pswd字符串变量的值,写入全局变量.似乎在经过一个计算函数和一个检查函数后,会输出成功信息.
全局函数指针0x4210有三个交叉引用,一个初始化赋值,一个调用,还有一个置0.
赋值后函数指针的值所对应的函数是一个简单的字符串比对,似乎是正确答案.
进入疑似计算的函数,2110函数.发现有异或,patch,说明可能不是之前想的那样.
先检查了字符串是否全部为小写16进制字符.然后就是patch赋值.
仔细分析赋值,他备份并赋值了一个QWORD(8 bytes),其中QWORD分成两个DWORD.第一部分等于2313(十六进制为0x909),第二部分的最终结果是0x1ee0,像是一个RVA,被赋值QWORD的rva是0x3218.
又观测到此处将上文的全局函数指针赋值为0,而且这个函数的调用在函数指针的调用之前,所以对于函数指针的调用将会触发异常.
跟进rva 0x3218,可以发现这里patch的是异常结构体.
16进制编辑器打开,修改异常数据,重新使用ida加载,发现这个patch的目的是动态添加异常处理函数.跟进动态添加的异常处理函数0x1ee0.
转到0x1ee0,发现是另一个函数.同样读取了全局变量密钥,同样会弹出对话框.
弹出的信息也有所不同,sha256变成了md4.由此可得,当输入密码为16进制小写字符串的时候,将会跳到0x1ee0函数.
跟进0x11f0,此函数执行了cmd命令,且与之前用来写入exe的路径有关.
关闭句柄后,调用ExitProcess(0),所以函数到这里结束,不会走另一个验证过程.其实从函数的调用约定__noreturn也能看出.
打开输入的参数字符串,得知这是经典的ping延时自删除,不过删的是之前hh.exe释放的整个chm的反编译内容的所在目录(包含本exe).
回到0x1ee0,函数将密码字符串传入了0x1e30,跟进0x1e30.
先patch,后调用0x1000.这个patch把0x4218的值写回了之前patch的异常结构体地址,应该是恢复之前的异常配置.
0x1000计算了输入宽字符串的长度.所以前面比对的是输入密码的长度.由此可得密码长度必须为4.
得到密码长度为4之后,继续往下看.
跟进0x1d10,再次发现patch.
这个lpText正是另一个成功信息.程序变更了该字符串的保护,在里面寻找字符L’4′,然后加一写回,并恢复保护.
而这里为L’4’的字符只有一个,所以这里是把信息中的’md4’改为了’md5′,修改了提交答案的方式.
跟进0x1b50.
跟进0x13b0.能发现sha3的一些常量.由题目名”3_idiots”可推得,”3_idiots”=>”3傻”=>”SHA-3″.所以大胆猜测此处调用了sha-3函数.
返回0x1ee0,可得0x1d10为sha-3哈希函数.这里将输入密码sha-3哈希两次,与常量数组比对.常量数组长度为32bytes,所以使用的是sha3-256.
若比对通过,则弹出对话框,内容正是之前patch”md4″为”md5″的那个字符串.
所以抠出sha-3两次哈希的结果,使用python爆破4bytes 16进制小写字符串的密码,最后进行md5哈希,然后再取大写16进制,包上”flag{}”后即可提交.
参考脚本如下:
import hashlib
def hashes(input_str):
first_hash = hashlib.sha3_256(input_str.encode()).digest()
second_hash = hashlib.sha3_256(first_hash).hexdigest()
return second_hash
def brute(target_hash):
hex_chars = '0123456789abcdef'
for c1 in hex_chars:
for c2 in hex_chars:
for c3 in hex_chars:
for c4 in hex_chars:
pswd = c1 + c2 + c3 + c4
if hashes(pswd) == target_hash:
md5_hash = hashlib.md5(pswd.encode()).hexdigest().upper()
return (pswd, md5_hash)
target = "9abdbc58792a7e9bff2249854f0a1e2c0bcb28d893e950fbee2f7d3abdfa9dea"
password, md5_result = brute(target)
print(password)#"fade"
print('flag{%s}'%md5_result)#"flag{CC3216B3C60FD8EA5C7A8ABCD3DE6F82}"
flag如下:
flag{CC3216B3C60FD8EA5C7A8ABCD3DE6F82}
2700勒索病毒排查
题目描述
某公司财务机器某天突然卡顿,任务管理器发现有程序在高占用,后续所有文件都无法打开,且所有文件都变成了.2700结尾的扩展名,目前通过一些特征判断是勒索病毒,比如勒索信以及文件名等,请您上机排查,并根据题目指引进行溯源和数据恢复。
所需工具在C:\Users\Solar\Desktop\工具\目录中
账号:Solar
密码:Solar521
靶机使用说明:青少年CTF平台Windows环境靶机使用说明
题解思路
本次题目环境和上次Live勒索病毒不同(利用WEB漏洞攻击),全网首发!教科书式学习勒索溯源排查(附开源环境+溯源报告),而本次侧重于”人”,比如通过钓鱼的方式进行攻击,简单粗暴,所以本次除了勒索排查与数据恢复外,还有对于钓鱼相关的溯源知识
1.提交勒索家族的名称
此勒索家族名称是什么?可访问应急响应.com进行查询,大小写敏感,最终以flag{}提交
在上方的教科书排查勒索的文章中我们提到,确认勒索家族是为了更好的了解此家族,比如此家族TTPs特征、此家族是否在互联网存在恢复工具等,那么有哪些特征可以确认家族呢?
1.加密文件扩展名
2.勒索信内容特征
3.联系邮箱
当然以上为一些判断条件作为特征进行鉴别
在本次环境中我们得到如下信息
1.扩展名:2700
2.邮箱:[email protected]
3.勒索信文件名:info.txt info.hta
4.以及给到的勒索内容
根据勒索信息我们根据题目描述指引,前往:http://应急响应.com 查询
根据其特征确定为勒索家族为:Phobos,由于flag大小写敏感,所以flag为:flag{Phobos}
2.勒索病毒预留的ID是什么
勒索病毒预留的ID是什么(预留ID为勒索组织恢复的凭证),以flag{}提交,如有多个以&进行连接
之前的文章我们提到过,勒索预留的id是勒索组织恢复的凭证,一般id存在于:
1.被加密文件名中
2.勒索信中
3.勒索信文件名
其次为了确认是否存在多个id,比如黑客加密了多次,可能会产生多个id的情况,我们可以借助桌面\工具\everything工具进行搜索
目前.2700扩展名的文件有9307个(可能有浮动),然后输出.2700 4A30C4F9-3524
数量一致,所以本次环境的id数量共一个
根据本次环境的被加密文件名和勒索信(info.hta)内容中提到的,且使用everything筛选后,id为:4A30C4F9-3524
所以本题目的flag为:flag{4A30C4F9-3524}
3.提交开始加密的时间
提交开始加密的时间,以flag{2025/1/1 11:11}格式提交
一般情况下加密开始时间点可以用于确认攻击时间点进行溯源,对于加密开始的时间如何确定,我们可以借助everything工具进行辅助
在桌面\工具\everything工具中,以管理员权限打开它
我们前面排查到被加密文件的扩展名为:2700,所以以此扩展名进行搜索
然后在Date Modified进行排序
通过对时间进行排序后得知最早开始加密的时间为:2025/11/19 14:31,所以flag为:flag{2025/11/19 14:31}
4.数据恢复
访问:应急响应.com 找到此家族恢复工具进行恢复,提交C:\Users\Solar\Desktop\Simulation_Desktop_Files\flag.txt文件中的flag
首先此家族的本次所用环境加密器已由:solar应急响应团队 破解,相关文章可参考:【病毒分析】phobos家族2700变种加密器分析报告
本次平台传输文件需要使用nas,相关文档可以参考:青少年CTF平台Windows环境靶机使用说明
访问应急响应.com后,在恢复工具侧找到Phobos恢复工具进行下载
下载恢复工具的程序的机器打开CMD,执行如下命令登录NAS
sftp -P 2222 手机号@nas.qsnctf.com
将恢复工具put至nas的home目录中,然后来到环境中,打开任一文件夹,输入如下:
\\nas.qsnctf.com
将tools.zip复制到相关到桌面并解压
为了节省时间,可以选择只恢复桌面的文件
等待一段时间过后看到,相关文件已经恢复完毕
来到Simulation_Desktop_Files目录查看flag.txt
最终flag为:flag{6eff1ea09e63423a48288a77d97e0cc6}
5.提交发送邮件的邮箱
提交C:\Users\Solar\Desktop\工具\mail 发送邮件的邮箱,以flag{[email protected]}格式提交
接下来开始进行溯源阶段,正常情况下溯源,我们需要了解此系统中开放了哪些端口,搭建了哪些业务,比如对外开放了RDP端口,是否搭建了某AO、ERP的服务?
通过netstat查看到开放了有25邮件端口,SMB共享,3389RDP端口,先看看3389端口的日志,比如爆破?
如上图所示,左下角输入event,查看事件日志,因为上面溯源的加密开始时间是11月19号 14:31,所以在安全日志中往下滑,找找14:31附近的日志
但是出乎意料的是这个时间之前的日志没了,一般我们认为,要不就是被删了,要不就覆盖了
通过属性确定大小,确实是被覆盖了,所以在日常我们做日志备份和设置日志大小的时候一定要做好相关配置,覆盖后对于溯源难度很大
但是我们本次溯源以人为本,这次是财务主机被勒索,比如财务收到钓鱼邮件后导致后续事件的发生,在题目中也给到了提示,相关的邮件在工具\mail目录中
同样的还是用nas传入文件到本地
这里我传入到本地后用foxmail打开邮件
根据题目要求得到了发件人的邮箱为:[email protected],所以本题的flag为:flag{[email protected]}
6.提交发送邮件的IP
提交C:\Users\Solar\Desktop\工具\mail 发送邮件的IP,以flag{x.x.x.x}格式提交
在发送邮件时,一般会记录客户端的IP,当然有些匿名邮箱是不记录的,以foxmail为例,右键邮件后点击查看邮件源码
然后在头信息中找到X-Originating-IP,这个就是客户端IP
所以得知此邮件发送IP地址为:39.91.141.213,故flag为:flag{39.91.141.213}
7.提交钓鱼附件中的C2
在钓鱼邮件中有一个名为:发票.zip 的附件
这可能就是本次钓鱼的C2,通过钓鱼上线后进行加密等,可以将此文件上传至沙箱平台
提交IP地址:182.9.80.123,所以flag为:flag{182.9.80.123}
8.恢复备份数据
部分数据丢失,好在运维之前做了备份,使用C:\Users\Solar\Desktop\工具\diskgenus恢复C:\Users\Solar\Desktop\工具\backup中的备份内:C:\Users\Solar\Desktop\flag.bak文件,提交其flag
本题目仿真了在实际生活中恢复备份的相关知识内容,比如勒索家族将一部分数据删除(而非加密),或者由于个人原因删除了一些数据,硬盘损坏等原因数据丢失,我们就会用到备份恢复相关了
打开桌面\工具\diskgenus后看到如下页面
此处只需要恢复指定文件而非全盘,所以这里打开虚拟磁盘文件即可
然后打开backup目录中的备份文件
因为只有一个盘,所以会显示1个分区,然后根据提示找到相关的flag.bak文件查看其中flag,也可以直接恢复到系统中
所以本题flag为:flag{92047522e5080bad36eda9d29d5a163e}
5.投票
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:solar应急响应团队 solarsec《2025-11月Solar应急响应公益月赛排名及官方题解》